Seria RCAI Învățământ la Distan ță [622467]
Seria RCAI Învățământ la Distan ță
404
UNIVERSITATEA DIN CRAIOVA
Facultatea de Matematic ă și Informatic ă
CENTRUL DE CERCETARE ÎN INTELIGEN ȚA ARTIFICIAL Ă
AUTOMATE, LIMBAJE Ș I
COMPILATOARE
ION IANCU
EDITURA SITECH
CRAIOVA, 2008
Referenți științifici:
Prof. univ. dr. NICOLAE ȚĂNDĂ REANU ,
Prof. univ. dr. ALEXANDRU DINC Ă,
Facultatea de Matematic ă și Informatic ă
Universitatea din Craiova
Automate, limbaje ș i
compilatoare
Titular: Prof. dr. Ion Iancu
Tutore: Prof. dr. Ion Iancu
Automate, limbaje și compilatoare 3
Algoritmi genetici 4
Despre Curs
Scurtă descriere a cursului.
Cursul are dou ă părți: prima se ocupa de Limbaje formale și automate iar a doua
de Proiectarea compilatoarelor.
În prima parte se studiaz ă noțiunile de gramatic ă și limbaj formal, automat finit și
automat pushdown. Se definesc aceste no țiuni, se arat ă cum se utilizeaz ă în
reprezentarea limbajelor și se demonstreaz ă echivalen ța limbajelor acceptate de
automate finite și respectiv pushdown cu limbajele generate de de gramaticile
regulate și respectiv independente de context. Se asemenea, se studiaz ă algoritmi
de simplificare a gramaticilor independente de context și clase speciale de astfel
de gramatici. Acest studiu este necesar deoarece gramaticile independente de
context sunt utilizate în specificarea sintaxei limbajelor de programare. Un
compilator se construie ște traducând, în mai multe etape, textul surs ă în cod
obiect. De aceea, partea a doua în cepe cu un studiu al metodelor de traducere. În
continuare se studiaz ă fiecare etap ă ce trebuie parcurs ă pentru a proiecta un
compilator, prezentându-se metode, algoritmi, exemple.
Obiectivele cursului.
– Cunoașterea modelelor matematice (gramatici și automate) folosite în
reprezentarea limbajelor, în general, și a celor de programare, în special.
– Cunoașterea pașilor ce trebuie parcur și în vederea proiect ării unui compilator și
a unor metode de a realiza ace ști pași.
Necesar Hardware și software pentru desf ășurarea cursului.
Calculator și soft adecvat (limbaj C, Java, etc) Despre Curs
Automate, limbaje și compilatoare 5
Automate, limbaje și compilatoare 6
Despre Curs
Curs 1 : Gramatici și automate finite……………………………………………… .. 9
Curs 2 : Limbaje independente de context……………………………………… .… 25
Curs 3 : Gramatici independente de context și automate pushdown………….. 39
Curs 4: Clase speciale de gramatici i ndependente de context (I)……… .……… 49
Curs 5 : Clase speciale de gramatici indepe ndente de context (II)…………… 63
Curs 6 : Teoria traducerii, analiz ă lexicală……………………………………… 81
Curs 7 : Algoritmi generali de analiz ă sintactică ………… ………………………. 101
Curs 8 : Analiza sintactică LL, LR și de precedență …………………………… . 115
Curs 9 : Analiza semantic ă………………………………………………………… . 129
Curs 10 : Generarea codului intermediar…………………… ………………….. 145
Curs 11 : Optimizarea codului ……………………………………………………… 163
Curs 12 : Generarea codului obiect………………………… …………………… 177
Curs 13 : Tabela de simboluri………………………………… ………………… … 193
Curs 14 : Tratarea erorilor…………………………………… ………………….. 207
Apendice A ………………………………………………………………………………………….. Apendice B ………………………………………………………………………………………….. Bibliografie ………………………………………………………………………………………….. 217
Note Aditionale ……………………………………………………………………………………. Cuprins
Automate, limbaje și compilatoare 7
Automate, limbaje și compilatoare 8
I. LIMBAJE FORMALE ȘI AUTOMATE
Curs 1 Gramatici ș i automate finite
Descriere General ă: Se studiaz ă n oțiunile de gramatic ă, automat finit ș i
legătura dintre ele din punct de vedere al limbajului
Obiective:
– însușirea noțiunilor: gramatic ă formală, limbaj formal, automat finit
– cunoașterea clasific ării Chomsky, a metodei de construire a gramaticii care
generează un limbaj ce con ține cuvântul vid, a verific ării recursivit ății
– cunoaș terea func ționării unui automat finit și a minimiz ării acestuia
– echivalarea limbajelor regulate cu li mbajele acceptate de automate finite
Cuprins
I.1. Clasificarea gramaticilor dup ă Chomsky
I.2. Automate finite
I.3. Relația dintre automate finite și limbaje regulate
Conținut Curs
I.1. Clasificarea gramaticilor dup ă Chomsky
Definiția 1.1. Fie V o mul țime finită și nevidă numită alfabet. Pentru
N notăm . Orice cuvânt îl notăm cu ,
iar numărul este lungimea cuvântului. Mul țimea are un singur element,
numit cuvântul vid și notat cu ∈ ∀k U
N kk *V V
∈=k
kV w w∈) , , (1L
0Vkw wL1
k
ε. Orice submul țime se numește limbaj
formal sau pe scurt limbaj. *VL⊂
Pentru descrierea limbajelor sunt folosite urm ătoarele metode:
– enumerarea elementelor, când limbajul este finit Curs 1
Durata :
2 ore
Automate, limbaje și compilatoare 9
– folosirea no țiunii de gramatic ă, atunci când limbajul este infinit.
Definiția 1.2. O gramatic ă este un sistem ()S P N G, , ,Σ= unde:
– N este un alfabet ale c ărui elemente se numesc neterminale și se noteaz ă cu
litere mari.
– este un alfabet ale c ărui elemente se numesc terminale și se noteaz ă cu litere
mici. Σ
– este mulțimea regulilor de produc ție. () () (* * *Σ ∪ × Σ ∪ Σ ∪ ⊆N N N N P )
– este simbolul ini țial . N S∈
Convenim ca orice element ()P v u∈,
*N. să-l notăm , specificând
astfel că se înlocuie ște cuvântul u cu cuvântul . Pentru orice producț ie
există cel pu țin o variabil ă în cuvântul u, deoarece
v u→
v v u→
()v u,() () ()* *Σ × Σ ∪ Σ ∪ ∈ N N N ∪
Definiția 1.3. Pe mulțimea cuvintelor se define ște relația binară “⇒”
astfel: ω⇒w (se citește derivează direct pe w ω) dacă
i) dacă βα, ,u∃ astfel încât βαu w= unde ()*, , Σ ∪ ∈N uβ α ,
ii) există o descompunere βαω v= , ()*Σ ∪și P v ∈N v u∈→ .
Această relație nu este neap ărat reflexiv ă și tranzitiv ă.
Definiția 1.4. Închiderea reflexiv ă și tranzitiv ă a relației o notăm cu
și o definim astfel: dacă = sau exist ă și
astfel încât ⇒
2w*
⇒
0,Z1w*
⇒
w2w
11w
1Z2w 1≥k
(*, Σ ∪ ∈ N ZkL )0 Z Zk=⇒ ⇒ ⇒ = L
*
⇒. Închiderea
tranzitivă o notăm cu și se defineș te eliminând din relația =w. +
⇒1w2
Derivarea în k pa și o notă m cu . k
⇒
Definiția 1.5. Se numește limbaj generat de o gramatic ă mulțimea:
{ S w G L*) (Σ ∈ =*
G⇒}w. Două gramatici care genereaz ă același limbaj se
numesc echivalente.
Definiția
gramaticii
Relația de
derivare
Limbaj
generat de o gramatică
Automate, limbaje și compilatoare 10
Impunând anumite restric ții producțiilor unei gramatici, Chomsky a introdus
trei tipuri de gramatici:
1. Gramatici dependente de context: orice produc ție P v u∈→) ( satisface
condiția v u≤ (gramatici de tipul 1), unde x este lungimea lui x.
2. Gramatici independente de context (GIC): orice producț ie
satisface condi ția P v u∈ →) (
1=u , , N u∈ε≠v (gramatici de tipul 2).
3. Gramatici regulate: orice produc ție P v u∈→) ( satisface condi ția
N u∈, N , v* *Σ ∪ Σ ∈ ε≠v (gramatici de tipul 3) dac ă N vΣ ∪ Σ ; ∈ ,
gramatica se nume ște în form ă redusă.
4. Gramatici care nu au nici un fel de restric ții impuse asupra produc țiilor
(gramatici de tipul 0).
Dacă s e n o t e a z ă cu , iL{}3 2 1 0, , , i∈ familia limbajelor generate de
gramatica de tip atunci . i0 1L L⊂ ⊂2L3L⊂
Teorema 1.1. Pentru orice gramatic ă de tip {}3 , 2 , 1∈i , există o
gramatică de acela și tip astfel încât simbolul ini țial S să nu apară în membrul
drept al nici unei produc ții.
Demonstra ție. Fie o gramatica de tipul ( S P N G, , ,Σ =) {}3 , 2 , 1∈i și
. Consider ăm gramatica Σ ∪ ∉ N S1 ( )1 1 1 1, , ,S P N1GΣ= unde {}1 1 S N N∪= ,
, . Evident, cele dou ă gramatici sunt de
același tip. Fie ; atunci, în G, există derivarea
. Din Σ = Σ1 P1
w S⇒ ⇒1(){ P w S∈ →
()G L∈
( w S}
)P/ w S P→ ∪ =1
w
w wk= ⇒ L ∈→1 rezultă c ă există ()1 1w S∈ →
G1P
1,
Cum , înseamn ă că toate deriv ările din G au loc și în .
Deci, în există derivarea , adică 1P P⊂
1G1+⇒i iw w
w S*
⇒1 ()1G L w∈ . Invers, fie ()1G L w∈ .
Înseamnă că în are loc derivarea 1G w wk w S =⇒⇒⇒1 1L . Din
()1P1 1w S∈ → rezultă c ă ()P w S∈ →1
S
1S, de unde ob ținem că nu conț ine pe
; deci, în gramatica G există derivarea . Prin induc ție după se arată
că niciun nu conț ine pe , deci toate deriv ările din au loc și în
. Deducem că în G are loc derivarea 1w
i1S
w
G1w⇒
⇒iw w
w Si
1G
w wk1+
=⇒⇒⇒1L ; deci
. ()G L w∈
Teorema 1.2. Dacă este un limbaj de tipul L {}3 , 2 , 1∈i atunci exist ă o
Clasificarea Chomsky
Automate, limbaje și compilatoare 11
gramatică care genereaz ă limbajul ( S P N G, , ,Σ =) {}ε∪L astfel încât
1) simbolul ini țial nu apare în membrul drept al niciunei produc ții din G S
2) în mulțimea P există producț ia ε→S
3) gramatica () S,1P N G, ,1Σ= , unde {}ε→= S P P\1 , este de tipul {} 3 , 2 , 1∈i
și genereaz ă limbajul . L
() S P, ,1
1PDemonstra ție. Din teorema anterioar ă rezultă existen ța gramaticii
de tipul , care genereaz ă limbajul iar simbolul
inițial nu apare în membrul drept al niciunei producț ii din . Adăugând
mulțimii producția N G,1Σ =
S{ 3 , 2 , 1∈i} L
G1
ε→S rezultă că {}ε∪=L G L) ( .
Spunem că limbajul peste alfabetul L Σ este recursiv daca există un algoritm
care pentru orice secven ță determin ă dacă *Σ ∈w L w∈.
Teorema 1.3. Limbajele de tip 1 sunt recursive.
Demonstra ție. Se utilizeaz ă
Algoritmul REC
Intrare : gramatica de tipul 1 și secvența de lungime l ), ,S PΣ, (N G=
w
0>l
() P S∈ →*Σ ∈w
Ieșire: mesajul DA dac ă ș i mesajul NU în caz contrar. ()G L∈
Metoda :
P1. Dacă , mergi la P3.
P2. Dacă ε atunci tip ărește DA
altfel tip ărește NU
STOP.
P3. {} 0 : ,=i S0=M
P4. (){ }β ⇒ α cu ∈ α ∃ ≤ β Σ+ Mși l / Mi*
i1 ∪ ∈ β ∪ =N Mi
i i M M≠+1
iM w∈
P5. Dacă atunci și mergi la P4. 1 :+ =i i
P6. Dacă atunci tip ărește DA
altfel tip ărește NU
STOP.
I.2. Automate finite
Un automat finit are dou ă componente principale: banda de intrare și
unitatea central ă. Banda de intrare este infinit ă la dreapta și este împ ărțită în
Testarea recursivit ății
Automate, limbaje și compilatoare 12
celule, în fiecare putând fi înscris un simbol din alfabetul de intrare Σ. Unitatea
centrală se poate afla într-un num ăr finit de st ări. În func ție de starea curent ă și de
simbolul citit de pe banda de intrare ea î și poate schimba starea.
Definiția 2.1. Se numește automat finit un sis ) ,0F tem , , , (q Q AδΣ=
unde :
– Q este mul țimea stărilor automatului
– este alfabetul de intrare Σ
– ) : Q ( QP→ Σ ×δ este func ția de tranzi ție
– este starea ini țială 0q
– F este mul țimea stărilor finale.
Funcționarea automatului se desc rie cu ajutorul configura țiilor.
Definiția 2.2. O configura ție a automatului este o pereche ()α,q unde
este starea curent ă iar q
α este secven ța de pe banda de intrare, r ămasă de citit.
Configura ția inițială este iar configura ția finală ) ,0wq( ) , (εq , unde Fq∈.
Funcționarea automatului se realizeaz ă prin pa și. Un pas reprezint ă
trecerea de la o configura ție la alta: ) , (αa q
) , (αp dacă ) , (a q pδ∈ . Notăm
cu
,
,
închiderea tranzitiv ă , închiderea reflexiv ă și tranzitiv ă și
respectiv trecerea în i pa și.
Definiția 2.3. Limbajul acceptat de un automatul finit A este mulțimea
{ ) , ( ) (0*w q w A LΣ ∈ =
}F p p∈), , (ε .
Descrierea și funcționarea unui automat finit ), , , , (0F q Q AδΣ= pot fi urm ărite
mai ușor dacă i se asociaz ă un graf G, astfel:
– mulț imea vârfurilor lui G este mulțimea Q a stărilor
– dacă , și Q q p∈, Σ ∈a (a p q,)δ∈ atunci se traseaz ă un arc de la vârful p la
vîrful q, care va fi etichetat cu a
– fiecare stare va fi scris ă într-un cerc
– starea ini țială va fi precedată de → iar stările finale vor fi scrise într-un cerc
dublu.
Un exemplu de astfel de reprezen tare este graful din figura 2.1
Definiția
automatului
finit.
Configuraț ie
Limbaj acceptat de un
automat finit
Automate, limbaje și compilatoare 13
0q1q fq
Figura 2.1
Definiția 2.4. Automatul finit ) , , , , (0F q Q AδΣ= se numește
– determinist , dacă Σ ∈ ∀ ∈ ∀ ≤a , Q q , ) a , q ( 1δ
– complet determinist, dacă Σ ∈ ∀ ∈ ∀ =a , Q q , ) a , q ( 1δ
– nedeterminist, în caz contrar.
Este clar că este mult mai convenabil s ă se lucreze cu auto mate finite complet
deterministe. De aceea urm ătoarea teorem ă este foarte important ă din punct de
vedere practic.
Teorema 2.1. Pentru orice automat finit nedeterminist ) , , , , (0F q Q AδΣ=
există un automat finit complet determinist 'A astfel încât ) ' ( )A L (A L= .
Demonstra ție. Construim automatul astfel 'A )' , ' , ' , , ' ( '0F q Q AδΣ= :
– )' Q ( QP=
– {}0 0 ' q q=
– {} ∅ ≠∩⊆ = F S Q S F / '
– ' ' : ' Q Q→ Σ ×δ , () ()
⎭⎬⎫
⎩⎨⎧∈ ∈ =
∈U
X pa p q Q q a X, / , ' δ δ
Este evident c ă automatul este complet determinist. 'A
Prin induc ție după i se arată c ă
()w X,
() ()w p X p Q q Y Y, , / { ,∈∃∈ = ⇔ ε
()ε,q }
unde w i= . Folosind aceast ă echivalen ță, pentru i x x= Σ ∈,*, rezultă
{}() x q A L x, ) ' (0⇔ ∈
()ε,Y și ' FY∈⇔
F Y q∩∈∃ ⇔ și ()x q,0
()ε,q ) (A L x∈⇔ ,
deci . )' ( ) (A L A L=
Construirea
automatului finit complet determinist
Automate, limbaje și compilatoare 14
Este de dorit ca un automat finit s ă aibă o structur ă cât mai simpl ă; o prim ă
posibilitate constă în eliminarea st ărilor inaccesibile.
Definiția 2.5. Fie ( F q Q A, , , ,0)δΣ = un automat finit și Q q∈. Spunem
că starea q este accesibil ă dacă există astfel încât *Σ∈x ()x q,0
()ε,q .
Altfel, starea se numește inaccesibil ă. q
Determinarea st ărilor accesibile se face cu urm ătorul algoritm
Algoritmul ACC
Intrare : automatul finit () F q Q A, , , ,0δΣ =
Ieșire: mulțimea a stărilor accesibile ale automatului aQ A
Metoda :
P1. {} 0 : ,0 0= =i q Q
P2. () {} a , q p cu a și Q q / Q p Q Qi i i δ∈Σ∈∃ ∈ ∃ ∈ ∪ =+1
P3. Dacă atunci și mergi la P2. i iQ Q≠+1 1 :+ =i i
P4. , STOP. i aQ Q=
Teorema 2.2 . Fiind dat automatul ( )F q Q A, , , ,0δΣ= , există un
automat (a a a a F q Q A, , , ,0)δΣ =
)aA care are toate st ările accesibile și
. ( ) (L A L=
Demonstra ție. Componentele automatului se obț in astfel: aA
– aQ se calculeaz ă cu algoritmul ACC
– ) :a a a Q ( QP→ Σ × δ este restric ția funcț iei δ
– a a Q F F∩ =
Eliminarea st ărilor inaccesibile se poate f ace pentru orice automat finit
(determinist sau nu). În continuare vom presupune ca auto matele finite cu care
lucrăm sunt complet deterministe si au numai st ări accesibile.
Definiția 2.6. Fie ( F q Q A, , , ,0)δΣ = un automat finit, și
. Spunem c ă secvența Q q q∈2 1,
*Σ ∈x x distinge st ările și dacă 1q2q()xq,1
()ε,1p ,
()x q,2
()ε,2p și exact una din st ările și este stare final ă. 1p2p
Stare
accesibilă
Automate, limbaje și compilatoare 15
Definiția 2.7. Spunem c ă stările și sunt -echivalente și notăm
dacă nu există nicio secven ță 1q2q k
2 1q qk
≡ x, cu kx≤, care să distingă și .
Stările și se numesc echivalente și se noteaz ă 1q2q
1q2q2 1q q≡ dacă sunt –
echivalente pentru orice num ăr natural . k
k
Este evident c ă și sunt rela ții de echivalen ță. Secvența vidă ≡k
≡ ε
distinge st ările și dacă și numai dac ă exact una dintre ele este stare final ă.
Deci, două st ări sunt 0-echivalente dac ă și numai dac ă sunt ambele finale sau
niciuna nu este final ă. De asemenea, din rezultă . 1q2q
21
1q qk
≡+
2 1q qk
≡
Teorema 2.3. Fie și două stări ale automatului finit 1q2q
() F q Q A, , , ,0δΣ =
, a q qk
21
1 Σ ∈ ∀ ⇔ ≡+ și un num ăr natural. Atunci
. k
(,2() a a , qk
1δ≡) qδ
Demonstra ție. Fie ; presupunem c ă 21
1q qk
≡+
Σ∈∃a astfel încât starea
nu este k-echivalent ă cu starea (a q p,1 1δ=) ()a q,2 p2δ= . Înseamn ă că există
cu *Σ ∈x k x≤ care distinge și , adică 1p2p ()x p,1
()ε, '1p ,
()x p,2
()ε, '2p și , (sau invers). Pentru secven ța , cu F p '2 p∈1' F Q\∈ ax
1+ ≤k1+=x ax , avem
()ax q,1
()x p,1
()ε, '1p
()ax q,2
()x p,2
()ε, '2p .
Rezultă c ă stările și n u s u n t î n r e l a ția 1q2q1+
≡k
, care este o contradicț ie; deci
presupunerea f ăcută este fals ă. Implica ția reciprocă se demonstreaz ă în mod
analog.
Definiția 2.8. Automatul finit A este redus dac ă toate st ările sunt
accesibile și nu are st ări distincte echivalente .
Teorema 2.4. Pentru orice automat finit complet determinist
( F q Q A, , , ,0)δΣ = există un automat finit redus 'A astfel încât ) ' ( ) (A L A L= .
Demonstra ție. Presupunem că automatul are toate stările accesibile.
Automatul redus se construiește cu algoritmul urm ător. A
Stări
echivalente
Automate, limbaje și compilatoare 16
Algoritmul RED
Intrare : automatul finit complet determinist ( )F q Q A, , , ,0δΣ= cu aQ Q= .
Ieșire: automatul finit redus astfel încât 'A )' ( ) (A L A L=
Metoda :
P1. []{} Q q / q Q ' Q/ ∈ = =≡
P2. []{} F q q F∈ =/ '
P3. ' ' : ' Q Q→ Σ ×δ , []()( )[][] Σ∈∀∈∀ = a , ' Q q , a , q a , q ' δ δ
P4. []() ' , , ' , , ' '0F q Q AδΣ =
Pornind de la 0
≡/Q{}F Q , F− =
k
≡1+
≡k și utilizând teorema anterioar ă se construiesc
relațiile , , …, = și se ia =1
≡2
≡ ≡k
≡; în acest moment se termin ă pasul P1.
Folosind defini ția lui 'δ rezultă ușor că automatul este redus. S ă arătăm că
cele două automate sunt echivalente. Fie . Dacă 'A
x*Σ ∈x ) (A L∈ atunci
()x q,0
()ε,q în A și F q∈.
Rezultă
[]()x , q0
[]()ε, q în 'A și [] 'F q∈ ;
deci . )' (A L x∈
Dacă ) atunci (A L x∉
()x q,0
()ε,q în și A F q∉.
Rezultă
[]()x q,0
[]()ε, q în și 'A[] 'F q∉ ,
adică ; deci, implică ) ' (A L x∉ ) ' (A L x∈ ) (A L x∈ .
I.3. Rela ția dintre automate finite și limbaje regulate
Vom arăta că familia limbajelor regulate coincide cu cea a limbajelor acceptate
de automate finite.
Teorema 3 .1. Pentru orice automat finit exist ă o gramatică regulată
astfel încât . A
G ) ( ) (G L A L=
Demonstra ție. Fie automatul ( )F q Q A, , , ,0δΣ= ; considerăm gramatica
Construirea automatului
redus
Automate, limbaje și compilatoare 17
(0, , ,q P Q GΣ =), unde produc țiile sunt de forma P
1) dacă Σ∈∈q p, a Q, și ()a p q ,δ∈ atunci ()P aq p∈→
2) dacă F q∈ atunci ()q→ P∈ε
Este evident c ă gramatica este regulat ă, în forma redus ă. Fie
;atunci ) (A L2 1a a a wn∈ =L
() q w q0 0,=(na a aL2 1,)
()na aL2q1,
…
()n na q,1−
()ε,nq
cu . Din F qn∈ ()i i i a q q,1−∈δ rezultă c ă pentru i i i q a q→−1 {}n i, , 2 , 1L∈ iar
din rezultă că F qn∈ () qn→ P∈ε . Deci, în G, au loc deriv ările
w a a q a a q a a q an n n = ⇒ ⇒ ⇒ L L L1 1 2 1 1 1 q0
) (G L w∈
) ( ) (A L G L⊆
N X∉⇒2
, ,Σ
Deci și . Reluând demonstra ția în sens invers, rezult ă că
, adică . ) ( ) (G L A L⊆
( ) (G L A L= )
Teorema 3.2. Orice limbaj regulat este ac ceptat de un automat finit
determinist.
Demonstra ție. Fie o gramatică regulat ă în formă redusă.
Fie și definim automatul nedeterminist ), (S P N G =
{}{}) , , , , (F S X N AN δΣ∪=
()} { {}
} {
⎪⎪
⎩⎪⎪
⎨⎧
= ∅∉ → ≠ ∈∈
P )P )
}
nx
⇒→ ∃ ∈∈ → ≠ ∪ → ∃ ∈
X YP ) x Y ( , X Y xA Y ( N AP ) x Y ( , X Y X xA Y ( N A
dacădacădacă
=x , Yδ
) (G L w∈
S⇒
{
⎩⎨⎧ ∈ →=
contrar caz îndacă (
} X {P ) S X , SFε
Fie , ; rezultă că ε ≠w, x x wL2 1=
n n n x x A x x A x x A x L L L1 1 1 1 2 2 1 1 1 ⇒ ⇒ ⇒− − .
Considerăm st ările X s A s A s S sn n n= = ==+ −1 1 1 2 1 , , , ,L . Avem
()()1 1 1 1 2 , ,x s x S A sδ=δ∈=
……………………………………………
() ()1 1 1 2 1 , ,− − − − − δ= δnA∈ =n n n n n x s x A s
() ()n n n n n x s x A X s, ,1 1 δ= δ ∈
w=− + .
Cum și , rezultă c ă S s∈1 sn F∈+1 )(A L∈ .
Fie ) (A L xn 1x w∈=L , (deci 1≥n ε≠w ). Rezultă c ă există stările
{} S S s=∈2s1 , , …., (1,sδ)1x∈ ()F x sn n sn ∈δ∈+ ,1 .
Există producț iile
Relația dintre
automate finite și gramatici regulate
Automate, limbaje și compilatoare 18
1 1 2 1 1A x s x s S=→ =
…………………………….
()1 1,− −δ∈n n n x s s
deci , adică ; n n n s x s1 1 − −→1 1 2 − − −→n n n A x A F sn∈+1 deci S sn=+1 sau .
Dacă tunci sn→ r S nu apare în membrul drept al produc țiilor,
deci X sn=+1 . Din n nx ,=X sn=+1
S sn=+1 a S xn; da
() (n, A s1−δ)nx Xδ∈ rezultă nA−1 n. Am ob
x S1⇒x→ ținut
n n n x x A x x A x x A L L L1 1 1 1 2 2 1 1 ⇒ ⇒ ⇒ ⇒− − , deci ) G ( L w∈ .
Dacă atunci ) G ( L w∈ ε = () P S∈ε→ , {}X , S F= , {}∅≠∩F S deci
) A. Invers, dac( L∈ ε ă ) A ( L∈ε atunci ()P S∈ε→ ,w ) G ( L∈ε= .
Acest au eterminist poate fi transformat, conform Teoremei 2.1, tomat finit ned
într-un automat finit determinist care accept ă acelaș i limbaj.
Automate, limbaje și compilatoare 19
Teme Curs
este Autoevaluare
1. Fie gramatica
T
{}{ } { } () S xSy S xy S y x S G, , , , ,→ → =
e aparț in lui avem . Precizați forma
elementelor car ()G L . ……………………. 2 puncte
B
De ce tip este gramatica …………………………………… 0.5 puncte
te
3. Consider2. Considerăm gramatica G cu produc țiile:
S→AB
B aB/CB →
Aa bC/Ca→
CB Ac/bAc →
bA → ba/AAB
a)
b) Folosind algoritmul REC, preciza ți dacă w=bac aparține sau nu lui
()GL ……………………………………………………………………….. 4 punc
ăm automatul {}{}{} ( )f f q q b a q q q A, , , , , ,0 1 0= cu
{}1 0) , (q a q=δ ,{}0 0) , (q b q=δ ,{}fq a q=) , (1δ ,
{}0 1) , (q b q=δ ,{}f f q a q=) , (δ ,{}f f q a q=) , (δ .
Verificați că aparține lui abaab w= ()A L. …………………..1.5 puncte
4. ă între ……… Ce relație exist1+
și k
≡ …………… 0.5 puncte 2 1q qk
≡2 1q q?
5. Ce relație există între automatele finite si limbajele regulate?…..0.5 puncte
6. Oficiu…………………………………………………………………… 1 punct
Automate, limbaje și compilatoare 20
Răspunsuri
1.
(){ }… , 2 , 1 /= = n y x G Ln n.
a) gramatica este de tipu
, obținem succesiv:
P1. me
0
er 4
B}
r
c}
r
rgi la P4
rgi la P4
s: w∈L(G). 2. l 1
b) Aplicând Algoritmul REC
rgi la P3
P3 . L0 := {S}, i:=
P4. L1=L0∪{AB}
P5. i=1, m gi la P
P4. L2= L 1∪{AaB,AC
P5. i=2, me gi la P4
P4. L3= L 2∪{bCB,AA
P5. i=3, me gi la P4
P4. L4= L 3∪{bAc}
P5. i=4, me
P4. L5= L 4∪{bac}
P5. i=5, me
P4. L6=L5
P5. –
P6. DA
Stop
Răspun
3. Avem
()abaab q,0
()aab q,0
()ab q,1
()b qf,
()ε,fq
deci ()A L abaab∈ .
4. implică
ezen bil într-un automat finit dac ă și numai dac ă el 2 1q q1k
≡+
2 1q qk
≡
5. Un limbaj este repr ta
este regulat.
Rezumat: s-au definit no țiunile de gramatic ă, limbaj generat de o gramatic ă,
automat finit, limbaj accepta t de un automat finit, rela ția dintre automate
finite și gramatici, minimizarea automatelor finite.
Automate, limbaje și compilatoare 21
Lucrari Practice (Laborator/Seminar)
onținut Laborator/Seminar
e vor implementa al goritmi care realizeaz ă: verificarea apartenen ței unui cuvânt
eme Laborator/Seminar
1. Scrieți un program care s ă implementeze algoritmul REC.
e unui automat
i un program care s ă simuleze funcț ionarea unui automat finit.
C
S
la limbajul generat de o gramatic ă, determinarea st ărilor accesibile în vederea
simplificarii structurii automatului, func ționarea unui automat finit.
T
2. Scrieți un program care s ă determine stările accesibile al
finit.
3. Scrieț
Rezumat: Implementarea unor algoritmi care s ă aprofundeze lucrul cu
gramatici și automate finite
Automate, limbaje și compilatoare 22
Notații
Automate, limbaje și compilatoare 23
Automate, limbaje și compilatoare 24
Curs 2 Limbaje independente de context
Descriere Generală
Se studiaz ă proprietăți de derivare în gramaticile independente de context,
arbori de derivare (la st ânga sau la dreapta) și mai mul ți algoritmi de
simplificare a acestor gramatici.
Obiective
– cunoașterea unor propriet ăți cu privire la derivare
– înțelegerea diferen ței dintre derivarea la stânga și cea la dreapta și a
semnifica ției arborelui de derivare
– cunoa șterea principalilor algoritmi de simplificare a formei gramaticilor
independente de context
Cuprins
I.4. Generalit ăți referitoare la gramaticile independente de context
I.5. Simplific ări ale gramaticilor in dependente de context
I.5.1 Eliminarea -producțiilor ε
I.5.2. Eliminarea redenumirilor
I.5.3. Eliminarea si mbolurilor inutilizabile
Conținut Curs
I.4. Generalit ăți referitoare la gramaticile independente de
context
Gramaticile independente de context sunt folosite în descrierea
structurii sintactice a limbajelor de pr ogramare, gramaticile regulate neputând s ă
acopere gama tuturor construc țiilor sintactice admise de diverse limbaje de
programare. Vom pune în eviden ță cîteva propriet ăți importante ale acestor
gramatici.
Teorema 4.1. Fie o gramatică independent ă de context.
Dacă ) S , P , , N ( GΣ =Curs 2
Durata :
2 ore
Automate, limbaje și compilatoare 25
nα α αL2 1*
⇒β
atunci
nβ β β=βL2 1 și {} n , , , i ,i i L2 1∈ β⇒α∗
iar produc țiile folosite în cele dou ă derivaț ii sunt acelea și.
Demonstra ție. Se procedeaz ă prin inducț ie după lungimea k a derivației.
Pentru înseamn ă că există 1=k " A 'iαα=α și producția α→A ; deci se ia
și pentru "αα'iα = βj jα = β ij≠. Presupunem afirma ția adevarat ă pentru
derivații de lungime k și consider ăm una de lungime 1+k :
β ⇒ α α α+1
2 1k
nL .
Ultima deriva ție se scrie
β ⇒ γ ⇒ α α αk
nL2 1 .
Conform ipotezei de induc ție
nγγ=γL1 și ; {} n , , , i ,i i L2 1∈ γ⇒α∗
în plus, deriva țiile din
γ ⇒ α α αk
nL2 1
sunt aceleaș i cu cele din
{} n , , , i ,i i L2 1∈ γ⇒α∗.
Din
β ⇒ γ γ γnL2 1 ,
conform cazului , rezultă 1=k
nββββ L2 1= și {} n , , , i ,i i L2 1∈ β⇒γ∗
iar produc țiile folosite în aceste deriva ții sunt acelea și cu cele din .
În final rezult ă concluzia din teorem ă. β ⇒ γ γ γnL2 1
Definiția 4.1. Un arbore orientat și ordonat este un graf orientat cu
proprietățile:
1) Există un vârf r, numit rădăcină, care nu are predecesori
2) Fiecare vârf diferit de r ădăcină are exact un predecesor
3) Există un drum de la r la fiecare vârf diferit de r ădăcină
4) Pe mulțimea succesorilor fiec ărui vărf este definit ă o relație de ordine
totală.
Proprietate de
derivare
Arbore
generator (de derivare)
Automate, limbaje și compilatoare 26
Definitia 4.2. Un arbore generator în gramatica independentă de context
) S , P , , N ( GΣ = este un arbore T orientat și ordonat, cu propriet ățile:
1) etichetele nodurilor apar țin mulțimii {}ε∪Σ∪N
2) eticheta oric ărui nod interior este un ne terminal al gramaticii
3) dacă n este nod interior cu eticheta A iar descenden ții lui, în ordine de
la stânga la dreapta, sunt kn ,L2 și au etichetele,
respectiv,kA , , atunci , n, n1
A , AL2 1 ( )kP A A A A ∈ →L21
4) dacă un nod are eticheta ε a t u n c i e l e s t e unicul descendent al
părintelui să u.
Dac ă în defini ția anterioar ă rădacina este etichetat ă cu atunci A T se va
numi -arbore . Un arbore generator se mai nume ște arbore de derivare. O
importanță deosebit ă au -arborii care au nodurile te rminale etichetate cu
elemente din mul țimea A
S
{ε ∪}Σ .
Teorema 4.2. În gramatica independent ă de context )S , P , , N ( GΣ=
există derivarea d a că și numai dac ă există un -arbore care produce pe
. α ⇒∗
A A
α
Demonstra ție. Se utilizeaz ă inducția după lungimea deriva ției si respectiv
după num ărul nodurilor interioare și se ține seama de defini ția arborelui
generator.
Se lucreaz ă cu deriva ții la stânga sau la dreapta. Spunem c ă α derivează
la stânga (dreapta) în β dacă de fiecare dată neterminalul care deriveaz ă este cel
mai din stânga (dreapta).
Unei deriva ții i se asociaz ă un arbore generator; totu și, este posibil ca o deriva ție
să aibă mai mul ți arbori generatori.
Definiția 4.3. O gramatic ă independent ă de context G este neambiguă
dacă orice secven ță admite o singur ă derivație la stânga (deci un
singur arbore generator); în caz contrar gramatica este ambigu ă. ) G ( L w∈
Gramaticile independente de context utiliz ate pentru a defini sintaxa limbajelor
Relația dintre
derivare și
arbore
Automate, limbaje și compilatoare 27
de programare trebuie s ă fie neambigue.
I.5. Simplific ări ale gramaticilor independente de context
Se urm ărește modificarea formei produc țiilor gramaticii astfel
încât să se elimine elementele redundante sau inutile sau s ă se obțină forme care
avantajeaz ă algoritmii de analiz ă sintactic ă.
I.5.1 Eliminarea -producțiilor ε
O producție este o produc ție de forma − ε ε→A . Prezen ța
producțiilor poate duce la deriva ții de lungime mare sau poate împiedica
folosirea unor algoritmi de analiz ă sintactică. Dacă limbajul generat de gramatic ă
conține cuvântul vid, va fi p ăstrată doar − ε
−εproducția ε→S .
Definiția 5.1. Fie o gramatic ă independent ă de context.
Simbolul este anulabil dac ă există o derivație de forma . )S , P , , N ( GΣ =
N A∈ ε ⇒∗
A
Simbolurile anulabile se determin ă cu
Algoritmul ANL
Intrare : gramatica ()S , P , , N GΣ = independent ă de context
Ieșire: mulțimea a simbolurilor anulabile anlN
Metoda :
P1. (){} 00 =∈ ε → ∃ ∈ = : i , P A / N A M
P2. () { }P A M / N A M Mi i i ∈ → ∈ ∃ ∈ ∪ =∗
+ α α încât astfel1
P3. Dacă atunci și mergi la P2. i iM M≠+1 1 :+ =i i
P4. , STOP. ianlM N=
Teorema 5.1. Pentru orice gramatic ă independent ă de context
există o gramatic ă independent ă de context astfel încât
. ) S , P , , N ( GΣ =
− =) G ( L ) ' G ( L' G
{}ε
Demonstra ție. Folosind algoritmul ANL se determin ă mulțimea a
simbolurilor anulabile. Fie anlN
() ε ≠ α ∈ α→ , P A , 1 2 1 1 +αααα=αk k kA AL .
Automate, limbaje și compilatoare 28
Se înlocuie ște fiecare produc ție 1 2 1 1 +αααα→k k kA A AL cu produc ții de forma
1 2 1 1 +αααα →k k kX X AL
unde
{ε ∈, A Xi i} dacă anl
iN A∈
și
i iA X= în caz contrar.
Apoi, se elimină din P toate producțiile. Notând cu − ε 'P mulțimea astfel
obținută, gramatica este ' G( )S , ' P , , ' GΣ = Nanl.
Ca o consecin ță, rezultă următoarea teorem ă, care a mai fost discutat ă anterior .
Teorema 5.2 . Pentru orice gramatic ă independent ă de context există
o gramatic ă independent ă de context ' ' echivalentă cu și care nu con ține
producții, exceptând eventual pe G
G G
− ε ε→' S ( fiind simbolul ini țial al
gramaticii ), caz în care nu apare în membrul drept al niciunei produc ții
din . ' S
' ' G ' S
' ' G
Demonstra ție. Fie gramatica construit ă în teorema anterioar ă. Dacă
atunci se ia . Dacă ' G
()G L∉ ε ' G " G= ()G L∈ε atunci se ia
. {} ∪ Σ' P , ' S , , ' S{→' S} () ε/ S ∪ =N " G
I.5.2. Eliminarea redenumirilor
O redenumire (sau produc ție singular ă) a unei gramatici independente de
context este o produc ție de forma . B A→
Teorema 5.3. Pentru orice gramatic ă independent ă de context f ără
producții există o altă gramatic ă de acela și tip și fără redenumiri,
echivalentă cu ea. − ε
Demonstra ție. Fie gramatica ini țială, astfel încât nu
apare în membrul doi al nici unei produc ții. Pentru fiecare ) S , P , , N ( GΣ = S
N A∈ definim
mulțimea . Deoarece G nu are
⎭⎬⎫⇒+
B A /
G ⎩⎨⎧∈ =N B ) A ( V−εproducții, toți
termenii deriv ării B Bk B A =⇒ ⇒L⇒1
kB , , BL1 au lungimea egal ă cu 1. Presupunând
că simbolurile sunt distincte, rezult ă că derivația este de B A∗
⇒
Eliminarea simbolurilor
anulabile
Automate, limbaje și compilatoare 29
lungime mai mic ă decât N; deci, mulț imile se pot calcula printr-un
proces iterativ în cel mult ) A ( V
1−N pași. Construim mulț imea de produc ții 'P în
felul următor:
1) eliminăm din P toate redenumirile
2) fie () P o produc ție singular ă; adăugăm la B∈ α → 'P toate produc țiile de
forma α → A pentru ) A ( V. B∈
În final lu ăm , care este independent ă de context și fără
redenumiri. Este evident c ă ) S , ' P , , N ( ' GΣ =
()()G L⊆' G L , iar incluziunea invers ă se demonstrează
ușor.
Acum se poate demonstra echivalen ța gramaticilor regulate cu cele în forma
redusă.
Teorema 5.4. Pentru orice gramatic ă de tipul 3, )S , P , , N ( GΣ= , există o
gramatică de acela și tip ) S , P , , N ( G1 1 1 1 1Σ=
v u→ echivalentă cu și având
proprietatea c ă orice produc ție satisface condi ția G
1 1 1N vΣ∪Σ∈ ; o astfel
de gramatic ă se nume ște în form ă redusă.
Demonstra ție. Conform teoremei anterioare exist ă o gramatic ă
de acelaș i tip cu G, echivalentă cu ea și fără redenumiri.
Producțiile gramaticii fiind de forma cu , pentru fiecare
producție de forma ) S , ' P , , N ( ' GΣ =
' G v u→ N* *Σ ∪ Σ v∈
Y a … a Xn 1→ , cu Σ∈na ,…, a1 , N Y , X∈ și , 2≥n
introducem variabilele , distincte și verificând condi ția
pentru orice . Adăugăm mul țimii aceste variabile, iar în 1 1 −nA …, , A
}1−nΣ ∉ Ai∪N
{2 1∈ …, , , i N 'P
în locul producț iei
Y a … a Xn 1→
introducem produc țiile
1 1A a X→ , , ….., . 2 2 1A a A→ Y an An→−1
Procedând astfel pentru toate produc țiile și apoi și pentru cele de forma
na … a X1→ cu Σ∈na ,…, a1 , N X∈ și , 2≥n
în acest caz având în loc de , obț inem o mul țime de
neterminale și o mulț ime de produc ții . Gramatica n n a A→−1 Y an→An−1
1P1N ) S , P , , N ( GS=Σ=1 1 1 1 1
este de acela și tip cu , deci ș i cu G. ' G
Algoritmul de
eliminare a redenumirilor
Echivalarea
gramaticilor
regulate cu cele în form ă
redusă
Automate, limbaje și compilatoare 30
I.5.3. Eliminarea simbolurilor inutilizabile
Definiția 5.2. Fie o gramatic ă independent ă de context.
Simbolul se nume ște utilizabil dac ă există o deriva ție de forma
; altfel )S , P , , N ( GΣ =
Σ ∪ ∈ N X
∗∗
Σ ∈ ⇒w∗
⇒X Sβ α X este inutilizabil.
Calitatea de simbol utilizabil poate fi verificat ă în două etape, conform
definițiilor următoare.
Definiția 5.3. Fie o gramatic ă independent ă de context.
Simbolul se nume ște productiv dacă există o deriva ție de forma
; altfel simbolul se nume ște neproductiv. )S , P , , N ( GΣ =
N A∈
∗Σ∗
∈ ⇒wA
Definiția 5.4. Fie o gramatic ă independent ă de context.
Simbolul se nume ște accesibil dac ă există o deriva ție de forma
; altfel simbolul se nume ște inaccesibil. )S , P , , N ( GΣ =
Σ ∪ ∈ N X
β αX S∗
⇒
Teorema 5.5. Fie o gramatic ă independent ă de context.
Există o gramatic ă independent ă de context ș i echivalent ă cu G, care are
toate simbolurile neterminale (exceptând eventual ) productive. )S , P , , N ( GΣ =
' G
S
Demonstra ție. Simbolurile productive se determin ă cu
Algoritmul PROD
Intrare : gramatica ()S , P , , N GΣ = independent ă de context
Ieșire: mulțimea a simbolurilor productive prodN
Metoda :
P1. () { } 0 încât astfel0 = ∈ → ∃ Σ ∈ ∃ ∈ =∗: i , P x A , x / N A M
P2. () () { }P A M / N A M Mi i i ∈ → Σ ∪ ∈ ∃ ∈ ∪ =•
+ α α încât astfel1
P3. Dacă atunci și mergi la P2. i iM M≠+1 1 :+ =i i
P4. , STOP. iprodM N=
Fie ( )S , ' P , , S N ' GprodΣ ∪ = , unde mul țimea 'P conține producț iile din P
formate numai cu simboluri din din {}∪S NprodΣ ∪.
Algoritm de
determinare a simbolurilor productive
Automate, limbaje și compilatoare 31
Din rezultă P ' P⊆ ()( G L ' G L⊆). Apoi, deoarece orice deriva ție
foloseș te numai produc ții din ∗∗
Σ ∈⇒w S
G
'P, rezultă ()()' G L G L⊆ si deci ()()' G L G L= .
Consecin ța 5.1. Dacă ) S , P , , N ( GΣ= este o gramatic ă independent ă de
context atunci ()∅≠G L dacă și numai dac ă este simbol productiv. S
Deoarece există un algoritm pentru determinarea simbolurilor productive,
înseamnă că problema mul țimii vide pentru limbaje independente de context este
rezolvabil ă algoritmic.
Teorema 5.6. Pentru orice gramatic ă independent ă de context există
o gramatic ă independent ă de context ", cu toate simbolurile accesibile și
echivalentă cu G. G
G
Demonstra ție. Mulțimea simbolurilor accesibile se determin ă cu
Algoritmul ACS
Intrare : gramatica ()S , P , , N GΣ = independent ă de context
Ieșire: mulțimea a simbolurilor accesibile acsN
Metoda :
P1. {} 00= =: i , S M
P2. () {} P X A N M A / N X M Mi i i ∈→∃ ∩∈ ∃ Σ ∪ ∈ ∪ =+ βα încât astfel1
P3. Dacă atunci și mergi la P2. i iM M≠+1 1 :+ =i i
P4. , STOP. iacsM N=
Gramatica este " G ( )S , " P , N , N N " Gacs acs∩ Σ ∩ = , unde conține toate
producțiile din " P
P formate numai cu simboluri accesibile.
Teorema 5.7. Fie o gramatică independent ă de context ( S , P , , N GΣ =)
)cu . Atunci exist ă o gramatic ă independent ă de context și fără
simboluri inutilizabile echivalent ă cu G. ()∅ ≠ G L1G
Demonstra ție. Fie gramatica echivalent ă cu , care nu
conține simboluri neproductive și ( S , ' P , , ' N ' GΣ = G
( )S , " P , " , " N " GΣ= gramatica echivalent ă cu
și care are toate simbol urile accesibile. Rezult ă că ' G ()()( " G L G L G L) '== și
rămîne de ar ătat că are toate simbolurile utilizabile. Deoarece orice " G " N A∈
Algoritm de
determinare a
simbolurilor accesibile
Automate, limbaje și compilatoare 32
este accesibil pentru , există derivația . Cum toate simbolurile din
secvența sunt productive pentru gramatica , înseamn ă că există derivația
. Toate simbolurile din ultimele dou ă derivații sunt accesibile
pentru G și ; deci simbolul este utilizabil în . " G
∗
⇒
" Gββ αA S
" G⇒∗
' G
Aβ αA
∗Σ ∈w
" S∗
⇒A
' Gβ α
∗∗
Σ ∈ ⇒ w A
" Gα " G
Automate, limbaje și compilatoare 33
Teme Curs
Teste Autoevaluare
1. Fie gramatica cu produc țiile
AB S→
ε→ / aAb A
ε→ / Bc B
Construi ți un S-arbore de derivare asociat……………………………….…. 1 punct
.
2. Consider ăm gramatica cu produc țiile
T / T E E+ →
F / F * T T →
a / ) E ( F→
și secvența ()a a a w+ ∗= .
Construi ți o derivare la stânga pentru ……………………………………. 1 punct w
3. Fie gramatica ) S , P , , cu produc țiile ε.
Precizați dacă gramatica este sau nu ambigu ă. Justifica ți răspunsul. N ( GΣ = → / SbSa / SaSb S
……………………………………………………………….……1 punct
4. Fie gramatica cu produc țiile
S aSb | aA | b , A bA , B→bS | b | c → →
Care este mul țimea simbolurilor productive? ………………..….. 2 puncte
5. Care sunt simbolurile accesibile ale gramaticii anterioare?……… 2 puncte
6. Fie gramatica cu produc țiile
S → aAB | AC
A →bA | CC
B SB | b →
C aCb |ε →
Determina ți mulțimea simbolurilor anulabile………………..……2 puncte
7. Oficiu………………………………………………………………1 punct
Automate, limbaje și compilatoare 34
Răspunsuri
1. Un exemplu de S-arbore este cel din figura urm ătoare
.rS
A
a b A1n
2n
3n 4n5n6n
ε
2. O derivație la stânga a lui w este
()E a F a F F F T T E∗⇒∗⇒ ∗ ⇒ ∗ ⇒ ⇒ ()( T T a T E a+)∗⇒+∗⇒
() T F a+ ∗ ⇒()T a a+ ∗ ⇒()F a a+∗⇒ ()a a a+∗⇒
3. Gramatica este ambigu ă. Secven ța ()G L abab w∈∈ admite doi arbori
generator diferi ți
εεε ε
εε
4. M0={S,B}, M 1=M 0, Nod Pr={S,B}
5. M0={S}, M 1={S,a,b}, M 2=M 1, Nacs={S,a,b}
6. M0 = {C}, M 1 ={C,A}, M 2 ={C,A,S}, M 3 =M 2.
Prin urmare Nanl = {S,A,C}
Rezumat: S-a descris rela ția dintre derivare și arborele generator asociat și
s-au studiat algoritmi de si mplificare a gramaticilor independente de context
Automate, limbaje și compilatoare 35
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se urmărește echivalarea unei gramatici independente de context cu una care a
fost simplificată .
Teme Laborator/Seminar
1. Scrieți un program care s ă echivaleze o gramatică independent ă de
context cu una f ără simboluri productive.
2. Scrieți un program care s ă echivaleze o gramatică independent ă de
context cu una care are toat e simbolurile accesibile.
3. Scrieți un program care s ă echivaleze o gramatică independent ă de
context cu una f ără producții vide.
4. Scrieți un program care s ă echivaleze o gramatică independent ă de
context cu una care are toate simbolurile utilizabile.
Rezumat: Aplicațiile urmăresc trecerea de la o gramatic ă independent ă de
context la una în form ă mai simplă; se poate simplifica în cascad ă, la fiecare
pas simplificând gramatica de la pasul anterior .
Automate, limbaje și compilatoare 36
Notații
Automate, limbaje și compilatoare 37
Automate, limbaje și compilatoare 38
Curs 3 Automate pushdown și gramatici independente de
context
Descriere Generală
Se definesc no țiunile de automat pushdown, configura ție, limbaj acceptat.
Se demonstreaz ă echivalenț a dintre limbajul acceptat cu memoria vid ă și cel
acceptat dup ă criteriul st ării finale.
Se demonstreaz ă echivalen ța limbajului acceptat de un automat pushdown cu
cel generat de o gramatic ă independent ă de context
Obiective
– cunoașterea structurii și a modului de func ționare a unui automat pushdown
– stabilirea rela ției dintre automate pushdown și gramatici independente de
context
Cuprins
I.6. Funcționarea automatelor și relația cu limbajele independente de context
Conținut Curs
I.6. Funcționarea automatelor și relaț ia cu limbajele
independente de context
Automatele pushdown sunt mecanisme de recunoa ștere a limbajelor
independente de context. Numele este da t de organizarea memoriei auxiliare sub
formă de stivă.
Definiția 6.1. Se nume ște automat pushdown un sistem
unde: ) F , Z , q , , , , Q ( P0 0δ Γ Σ =
– Q este mul țimea stărilor automatului
– este alfabetul de intrare Σ
– este alfabetul intern (pushdown) Γ
– {}() ()*Q Q : Γ × → Γ × ε ∪ Σ × δfP e s t e f u n c ția de tranzi ție, unde P f e s t e Curs 3
Durata :
2 ore
Automate, limbaje și compilatoare 39
mulțimea părților finite.
– este starea ini țială Q q∈0
– este simbolul intern ini țial Γ ∈0Z
– este mulțimea stărilor finale. QF⊂
Definiția 6.2. Funcționarea automatului este dictat ă de func ția de
tranziție și se define ște cu ajutorul configura ției ) , w , q (γ, .
Configuraț ia inițială este . * *, w , Q qΓ ∈ Σ ∈ ∈γ
)Z , w , q (0 0
Trecerea de la o configura ți e l a a l t a s e f a c e p r i n p a și:
) Z , aw , q (γ
) , w , q (αγ1 dacă ) Z , a , q ( ) , q (δ∈α1 . Notăm cu
,
,
închiderea tranzitiv ă , închiderea reflexiv ă și tranzitivă și respectiv trecerea
în i paș i.
Definiția 6.3. Limbajul acceptat de automatul pushdown P după criteriul
benzii vide este: { ) Z , w , q ( w ) P ( L*
0 0 Σ ∈ =
}) , , p (εε .
Limbajul acceptat de automatul pushdown P dup ă criteriul str ării finale
este: { ) Z , w , q ( w ) P ( L*
0 0 Σ ∈ =
}F p ), , , p (∈αε .
Teorema 6.1. Fie un limbaj independent de context. Atunci există un
automat pushdown L
M astfel încât )M ( L Lε= .
Demonstra ție. Fie astfel încât ) S , P , , N ( GΣ = ) G ( L L= . Construim
unde: () ∅,δ Σ ∪ Σ = S , q , , N , , q M
t1) () ( ){} P ) A ( , q A , , q∈ α → α = ε δ
t2) . () ( ){} Σ ∈ ∀ ε = δa , q a , a , q
t3) în toate celelalte cazuri. () ∅ = δ Z , b , q
Tranzițiile t1) produc pe banda pushdown deriva ții la stînga din gramatica G iar
tranziț iile t2) permit trecerea la simbolul urm ător, pe benzile de intrare si
pushdown, în cazul coinciden ței dintre simbolurile citite de pe cele dou ă benzi.
Fie și ; trebuie stabilit ă echivalen ța N A∈∗Σ ∈w
(1) () A , w , q w A⇔ ⇒∗
()εε, , q
Demonstra ția de la stânga la dreapta se face prin induc ție după lungimea a k
Limbaj acceptat
Construirea
unui automat
pushdown cu memoria vid ă
care accept ă
un limbaj independent de
context
Automate, limbaje și compilatoare 40
derivației. Pentru , înseamnă 1=k w A⇒ ()P w A∈→ și .
Folosind t1) rezult ă ∗Σ ∈ =pa a a wL2 1
()()A , ,q w , q εδ∈ ,
deci
() A, w , q
()( )pa q w , w , qpa , a a ,L L1 1= .
Folosind p tranziții de tipul t2 rezult ă
( )p p a a , a a , qL L1 1
()εε, , q,
deci
() A , w , q
()εε, , q.
Presupunem implica ția “ ” adevărată pentru deriva ții de lungime mai mic ă
decât și fie . Înseamnă că ⇒
k w
Aα =1Ak
⇒
w A Ar r r∗
+⇒ α α α α ⇒1 2 1L , unde ,∗Σ ∈ αi N Ai∈
Rezultă descompunerea
1 2 1 1α α α = w wL+αr r rw cu și {} r , , , i , w Aiik
i L2 1∈ ⇒ 12 −1 =+++ k k krL k .
Conform ipotezei de induc ție,
(2) ()i iA , w , q
()εε, , q, {}r , , , iL2 1∈
Folosind t1), t2) și (2) rezult ă
() A , w , q
()( )1+αr rA2 1 1 1 2 1 1 +α α α α α =r r A , w w , qL L α, w , q
()1 2 1 1 2 + + 1 ααα αr r r r A A , wL L w , q
()1 2 1 + + 2 αα αr r r r A , wL Lα, q
()1 1+ +αr,αr, q
()εε, , q
Implicația inversă se demonstreaz ă prin induc ție după numărul de pa și din
() A , w , q
(ε, , q)ε. Dacă
() A , w , q
()εε, , q,
se aplică t1; deci
() P A∈ ε →, ε=w și . w A⇒
Presupunem implica ția adevărată pentru un num ăr de paș i mai mic decât și fie k
(3) () A , w , q
()εε, , q în k pași
La primul pas din (3) se folose ște t1. Aceast ă trecere se descompune în
() A, w , q
()( )1 2 1 1 +α α α = αr rA A , w , q , w , qL
()εε, , q
unde ultima trecere are loc în pași și 1−k
( )P A A Ar r∈ α α α = α →+1 2 1 1L .
Automate, limbaje și compilatoare 41
Rezultă și 1 1z wα =
(4) ( )1 2 1 1 1 1 +α α α αr rA A , z , qL
( )1 2 1 1 +ααr rA A , z , qL
()ε ε, , q.
Fie prefixul lui care se consumă de pe banda de intrare pân ă când
conținutul benzii pushdown devine pentru prima dat ă mai mic decât 1w1z
1 2L1 +α αr rA A ; deci
(5) ,1 1 1y w z=()1 1A , w , q
()εε, , q în 11−≤k k pași și 1 1w A∗
⇒
Din (4) și (5) rezult ă
()1 2 1 +ααr rA , y , qL
()εε, , q.
Repetând ra ționamentul se obț ine
1 2 1 1 +α α α α =r r rw w wL , ()i iA , w , q
()εε, , q în 1−≤k ki pași și conform
ipotezei de induc ție . iwiA∗
⇒
În final,
w w w A A Ar r r r r r = α α α ⇒ α α α = α ⇒+∗
+ 1 1 1 1 1 1 L L .
Luând în (1), rezult ă S A= ()()M L G L wε⇔∈ .
Teorema 6.2. Pentru orice automat pushdown M, ()M Lε este limbaj
independent de context.
Demonstra ție. Fie ( )∅ δΓΣ= , Z , q , , , , Q M0 0 . Construim
astfel ) S , P , , N ( GΣ =
[]{} {}S x , Q q , p / q , X , p N∪Γ∈∈ = ,
fiind simbol nou iar producț iile sunt de forma (Σ ∪ ∉ N S)
1. []q , Z , q S0 0→ pentru orice Q q∈
2. Dacă () ( ) Z , a , p și 0>r atunci X X , qrδ ∈L1
[] [ ] [ ] [ ]r r r r p , X , p p , X , p p , X , q a p , Z , p1 2 2 1 1 1 − → L
pentru orice Q p , , pr∈L1
3. Dacă ()()Z , a , p atunci , qδ ∈ ε []a q ,. Z , p→
Evident, este independent ă de context. Pentru a stabili egalitatea
se arată că are loc echivalen ța G
(Mε() ) L G L=
(1) [] () X , w , p w q , X , p⇔ ⇒∗
()εε, , q, Γ∈∈∀ X , Q q , p și ∗Σ ∈w
Implicația se demonstreaz ă prin induc ție după lungimea deriva ției iar cea
inversă, prin inducț ie după numărul de paș i. " "⇒
Limbajul acceptat cu
memoria
pushdown vid ă
este
independent de
context
Automate, limbaje și compilatoare 42
Fie ; rezultă (M L wε∈)
()0 0Z , w , q
()εε, , q cu Q q∈.
Din (1) rezult ă . Conform producț iilor de tipul 1, avem
, adică . Fie acum [] w q , Z , q∗
⇒0 0
L w∈ [] w q , Z , q S∗
⇒ ⇒0 0 ()G ()G L w∈ , adică . Primul
pas în aceast ă derivare este de forma . Ținând seama de (1),
rezultă w S∗
⇒
[, q S⇒0]w q , Z∗
⇒0
()0 0Z , w , q
()ε ε, , q, adică ()M Lε w∈ .
Am lucrat cu automate care se opresc dup ă criteriul benzii pushdown vide.
Acestea sunt, îns ă, echivalente, din punct de vedere al limbajului acceptat, cu
automate care se opresc dup ă criteriul st ării finale. Teoremele urm ătoare
demonstreaz ă această echivalen ță.
Teorema 6.3. Pentru orice automat pushdown P există un automat
pushdown 'P astfel încât . () () ' P L P L=ε
Demonstra ție. Fie () ∅ δΓΣ= , Z , q , , , , Q P0 0 ; am luat ,
deoarece st ările finale nu intervin în func ționare. Definim ∅ =F
{}{} {} ( )fq , X , ' q , ' ,0 f X , , q , ' q Q ' P0 δ∪ Γ Σ ∪ =
unde și sunt stări noi iar 0' qfq X este simbol nou. Funcț ia de tranzi ție este
difinită prin
t1) () ( {} X Z , q X , , ' q '0 0 0= ) εδ
t2) () () {}Γ∈∀ε∪Σ∈∀ ∈ ∀ δ = δ Z , a , Q q Z , a , q Z , a , q '
t3) ()(){}ε εδ , q X , , q 'f=
t4) ia ca valoare ∅ în celelalte cazuri. 'δ
Tranziția t1) aduce automatul 'P în configura ția inițială a automatului P, având
în plus simbolul X la baza stivei. Tranzi țiile t2) permit automatului 'P să
simuleze automatul P. Dacă, în urma simul ării, automatul 'P rămâne doar cu
simbolul X pe banda pushdown (ceea ce corespunde golirii benzii pushdown a a
lui P) atunci 'P trece, prin tranziț ia t3), în starea final ă . Dacă, în plus, a fost
citită toată banda de intrare, atunci fq
'P este într-o configura ție de acceptare.
Teorema 6.4. Pentru orice automat pushdown P există un automat
pushdown 'P astfel încât . () () ' P L P Lε=
Teoreme 6.3 și
6.4
demonstreaz ă
Automate, limbaje și compilatoare 43
Demonstra ție. Fie ( )F , Z , q , , , , Q P0 0δΓΣ= . Construim
{}{} ( )∅δ ∪ Γ Σ ∪ =ε , ' q , ' , X , , q ' q Q ' M, 0 0
Γ ∉X, Xεq ' q0
', unde și două stări distincte ,
care nu apartin lui Q, iar . Funcția de tranziț ie δ este definit ă astfel
t1) {} ) X Z , q ( ) X , , ' q ( '0 0 0= ε δ
t2) pentru , () ( Z , a , q Z , a , q 'δ ⊇ δ) Q q∈ ∀ {}ε∪Σ∈∀a și Γ∈∀Z
t3) { ) , q ( ) Z , , q ( '}ε εδε⊇ pentru F q∈∀ și Γ∈∀Z
t4) { ) , q ( ) Z , , q ( '}ε εδε ε= pentru {}X Z∪Γ∈∀
t5) ia valoarea ∅ în rest. 'δ
Tranziția t1) aduce automatul 'P în configura ția inițială a lui P, cu deosebire că
la baza benzii pushdown se afl ă simbolul X. Rolul lui X este de a evita golirea
simultană a benzilor de intrare și pushdown făr ă ca automatul s ă fie în stare
finală. Tranzițiile t2) permit automatului 'P s simuleze funcț ionarea lui ă P. Daă c
'P ajunge într-o stare finală atunci el poate efectua fie tranzi ții de tipul t2) fie
poate intra în faza de golire a benzii pushdown prin tranzi ții de tipul t3).
Tranzițiile t4) permit golirea benzii pushdown.
Consecin ța 6.1 . Pentru orice limbaj , urm ătoarele afirma ții sunt
echivalente L
1) este independent de context L
2) este acceptat de un automat pushdown dup ă criteriul benzii
pushdown vide L
3) este acceptat de un automat pushdown dup ă criteriul st ării finale. L
Definiția 6.4. Automatul pushdown ( )F , Z , q , , , , Q P0 0δΓΣ= este
determinist dac ă
1) () {}Γ ∈ ∀ ε ∪ Σ ∈ ∀ ∈ ∀ ≤ δZ , a , Q q , Z , a , q 1
2) () ()∅≠δΣ∈∀⇒∅≠ε δ Γ ∈∀ ∈ ∀ Z , a , q , a Z , , q , Z , Q q .
Între automatele pushdown nedeterministe și deterministe nu exist ă o
relație similar ă cu cea din cazul automatelor finite. Justificarea acestei afirma ții
este urm ătoarea: se verific ă ușor că limbajele {}0 1 01 ≥ =n / Ln n și
{}1 1 02
2 ≥ = n / Ln n sunt independente de contexe, deci și 2 1L L L∪= este
independent de context. Înseamn ă că există un automat pushdown care accept ă pe
; totuși, s-a demonstrat c ă, nu exist ă automate pushdown deterministe care s ă
accepte pe . L
Lechivalen ța
dintre limbajul
acceptat dup ă
criteriul st ării
finale și cel
acceptat cu memoria vid ă
Sinteza
teoremelor din
curs
Automat pushdown
determinist
Automate, limbaje și compilatoare 44
Teme Curs
Teste Autoevaluare
1. Care sunt componentele unui automat pushdown?…………………… 2 puncte
2. Definiți noțiunea de configura ție………………………….……… 1 punct
3. Care sunt criteriile dup ă care este acceptat un limbaj?………………..2 puncte
4. Ce legatur ă există între cele dou ă moduri de acceptare……….….. 1 punct
5. Definiți noțiunea de automat pushdown determinist………..…… 2 puncte
6. Definiți relația dintre automate pushdown și gramatici independente de
context………………………………………………………………………….1 punct
7. Oficiu…………………………………………………………… 1 punct
Automate, limbaje și compilatoare 45
Răspunsuri
1. – Q este mulțimea stărilor automatului
– este alfabetul de intrare Σ
– este alfabetul intern (pushdown) Γ
– {}() ()*Q Q : Γ × → Γ × ε ∪ Σ × δfP e s t e f u n c ția de tranziț ie, unde P f e s t e
mulțimea părților finite.
– este starea iniț ială Q q∈0
– este simbolul intern ini țial Γ ∈0Z
– este mulțimea stărilor finale. Q F⊂
2. ) , w , q (γ, * *, w , Q qΓ ∈ γ Σ ∈ ∈
3. criteriul benzii vide este:
{ ) Z , w , q ( w ) P ( L*
0 0 Σ ∈ =
}) , , p (εε .
criteriul str ării finale este:
{ ) Z , w , q ( w ) P ( L*
0 0 Σ ∈ =
}F p ), , , p (∈αε .
4. Un limbaj este acceptat de un automat pushdown dup ă criteriul st ării finale
dacă ș i numai dac ă este acceptat dup ă criteriul benzii vide
5. Automatul pushdown ( F , Z , q , , , , Q P0 0) δΓΣ= este determinist dac ă
1) () {}Γ ∈ ∀ ε ∪ Σ ∈ ∀ ∈ ∀ ≤ δZ , a , Q q , Z , a , q 1
2) () ()∅≠δΣ∈∀⇒∅≠ε δ Γ ∈∀ ∈ ∀ Z , a , q , a Z , , q , Z , Q q .
6. Pentru orice limbaj , următoarele afirma ții sunt echivalente L
1) este independent de context L
2) este acceptat de un automat pushdown dup ă criteriul benzii
pushdown vide L
3) este acceptat de un automat pushdown dup ă criteriul st ării finale L
Rezumat: S-a definit no țiunea de automat pushdow n, s-a demonstrat
echivalen ța dintre cele dou ă moduri de acceptare, și dintre automate
pushdown ș i limbaje independente de context.
Automate, limbaje și compilatoare 46
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se va însu și, pe baza unui program, modul de func ționare al unui automat
pushdown în vederea accept ării unui cuvant.
Teme Laborator/Seminar
1. Să se scrie un program care s ă simuleze funcț ionarea unui automat
pushdown determinist; analiza ți cele dou ă criterii.
Rezumat: Funcționarea automatelor pushdown
Automate, limbaje și compilatoare 47
Notații
Automate, limbaje și compilatoare 48
Curs 4 Clase speciale de gramatici independente de context
(I)
Descriere Generală
Se echivaleaz ă o gramatic ă independent ă de context cu alta:
1) în forma normal ă Chomsky
2) fără recursie la stânga
3) factorizată la stânga
Se stabile ște condiția necesar ă și suficient ă ca o gramatic ă independent ă de
context să fie LL
Obiective
– cunoașterea metodei de trecere de la o gramatic ă independent ă
de context arbitrar ă la una în forma normal ă Chomsky
– cunoaș terea algoritmului de înl ăturare a recursivit ății la stânga și a celui de
factorizare la stânga
– familiarizarea cu no țiunea de gramatic ă LL(k) și însușirea metodei de
verificare a condi ției LL
Cuprins
I.7.1 Gramatici în forma normal ă Chomsky
I.7.2. Gramatici nerecursive la stânga
I.7.3. Gramatici factorizate la stânga
I.7.4. Gramatici LL(k)
Conținut Curs
I.7.1 Gramatici în forma normal ă Chomsky
Una din simplific ările de baz ă aduse produc țiilor unei gramatici
independente de context este enun țată într-o teorem ă dată de Chomsky. Orice
gramatică ale cărei produc ții satisfac aceast ă teoremă se nume ște în form ă
normală Chomsky.
Curs 4
Durata :
2 ore
Automate, limbaje și compilatoare 49
Teorema 7.1. Orice limbaj independent de context care nu con ține
cuvântul vid poate fi generat de o gramatic ă în care toate produc țiile sunt de
forma sau , unde sunt neterminale iar este terminal. YZ X→ a X→ Z, Y ,X a
Demonstra ție. Conform teoremei 1.14 este suficient să lucrăm cu
gramatici independente de context f ără redenumiri. Fie ) S , P , , N ( GΣ= o astfel
de gramatic ă și o produc ție a lui G. Dacă mY … Y X1→ 1=m , atunci este
terminal și această produc ție satisface forma normal ă Chomsky. Dac ă ,
atunci fiecare terminal , , din produc ție este înlocuit cu un nou simbol
diferit de toate simbolurile din 1Y
m2≥
iY≤1 m i≤
iZ Σ∪N și de simbolurile introduse anterior.
Reținem și produc ția , care satisface forma normal ă Chomsky.
Transformând astfel toate regulile ob ținem mulț imea de produc ții și o nouă
gramatică iY→iZ
1P
{}( , , Z NiΣ ∪
… A X1→
2−nB)
2>nS , P1
nAG1=
1…, , B echivalent ă cu G. Apoi, pentru fiecare
producție de forma , cu , din gramatica , se introduc
simboluri și producțiile 1G 2−n
(1) , , …, . 1 1B A X→2 2 1B A B→n n n A A B1 2 − −→
Procedăm așa cu fiecare produc ție care are cel pu țin trei simboluri în membrul al
doilea și adăugăm la mul țimea neterminalelor simbolurile noi. Înlocuim, apoi,
producția , cu , cu producț iile (1). Ob ținem o nou ă gramatic ă
independent ă de context, aflat ă în form ă normală Chomsky;
este echivalent ă cu și deci și cu G. nA … A X1→
) S , ' P ,Σ2>n
, ' N ( ' G=
' G1G
I.7.2. Gramatici nerecursive la stânga
Defini ția 7.1. Fie GIC ()S , P , , N GΣ= . Neterminalul X se nume ște
recursiv la stânga dac ă X
αX pentru un anumit ()*Σ N∪ ∈ α . Dacă
conține cel pu țin un neterminal recursiv la stânga, gramatica se nume ște cu
recursie stâng ă. G
Recursivitatea direct ă, ce apare pentru un neterminal A sub forma
producțiilor m n A / … / A / / … / / Aααβββ1 2 1→ , unde n ,,…,βββ2 1 nu se
pot scrie sub forma γA, se elimin ă înlocuind aceste produc ții cu
Echivalarea
unei gramatici independente de context cu
una in form ă
Chomsky
Echivalarea unei gramatici independente
de context cu
Automate, limbaje și compilatoare 50
ε α α αβ β β
/ A / … / A / A AA / … / A / A A
'
m' ' ''
n' '
2 12 1
→→
unde este un neterminal nou. 'A
Această procedur ă nu elimin ă, însă, recursivitatea stâng ă generată de deriv ări în
doi sau mai mulț i pași. În acest caz trebuie folosit urm ătorul algoritm:
Algoritmul NREC – de eliminare a recursiei la stânga
Intrare : gramatica G, fără cicluri și fără ε- producț ii
Ieșire : o gramatic ă echivalent ă cu G, dar fără recursie stâng ă
Metoda :
P1. ordoneaz ă neterminalele în ordinea nA ,…, A , A2 1
P2. for 1=: ito n do
for 1=: j to 1−i do
– înlocuie ște fiecare producț ie de forma
cu produc țiile α →j iA A
α βαβ α β →m i / … / / A2 1 dacă m j / … / Aββ→1 sunt toate
– producțiile jA
– elimin ă recursivitatea stâng ă directă a lui dacă este cazul. iA
I.7.3. Gramatici factorizate la stânga
Dac ă 2 1αβαβ/ A→ sunt două -producț ii, iar cuvântul de la intrare
începe cu α, nu ș tim dacă trebuie f ăcută o expandare a lui cu A
A1αβ sau cu
2αβ. Regulile de acest fel vor fi modificate astfel încât alternativele pentru
expandare să difere începând cu primul simbol.
Algoritmul FACT – de factorizare la stânga
Intrare : o GIC G
Ieșire : o gramatic ă echivalent ă, factorizată la stânga
Metoda : Pentru fiecare neterminal se determin ă cel mai lung prefix A εα≠
comun la dou ă sau mai multe alternative. Se înlocuiesc -producA țiile
γαβαβαβ / / … / / An 2 1 → , unde γ reprezintă toate alternativele ce nu încep cu
α, cu
n/ … / / ' A/'A A
β β βγα
2 1→→ una fără
recursie la
stânga
Algoritmul de eliminare a recursiei
Factorizarea la stânga
Automate, limbaje și compilatoare 51
unde 'A este un neterminal nou. Se repet ă această transformare pân ă când nu
mai există, pentru nici-un neterm inal, alternative care s ă aibă un prefix comun.
Exemplul 7.1. Factorizarea stâng ă a gramaticii cu produc țiile
d / aEbScS / aEbS S → , e E→
este
e E/ dS Sd / aEbSS S
''
→ε →→
I.7.4. Gramatici LL(k)
Fie o gramatic ă neambigu ă și ( S , P , , N GΣ =) ) G ( L a … a a wn∈ =2 1
, S0.
Atunci exist ă o unică derivare la stânga astfel încât 1 1 0−mp … p p α=1+⇒ip
ii
α α;
și . Dacă m i< ≤ 0 wm= α β α Aja … ai 1= , dorim ca secven ța 1+αi să poată fi
determinat ă cunoscând primele j simboluri (partea din cu vântul de intrare citit ă
până în acel moment), urm ătoarele simboluri ( pentru un anumit
=) și neterminalul . Dac ă aceste trei cantit ăți determin ă în mod unic produc ția
folosită pentru expandarea lui , vom spune c ă gramatica G este . În
continuare vom considera c ă neterminalul care deriveaz ă este cel mai din stânga. k
Ak
()k LLj ja …+ + 1a
k A
Defini ția 7.2. Fie ( S , P , , N G)Σ=
)( PRIMG
kα o GIC , un num ăr natural ș i
. Definim func ția astfel : k
(*NΣ ∪ ∈ α)
{ α < Σ ∈ = α si k w / w ) ( PRIM* G
k
w
α = si k w sau
} anumit un pentru wx x
Am notat cu x lungimea secven ței x. Dacă nu exist ă pericol de confuzie vom
renunț a să mai preciz ăm gramatica . G
Defini ția 7.3. Fie o GIC. Spunem c ă este
dacă: ( S , P , , N GΣ =) G()k LL
(1) S
αwA
βαw
wx
Automate, limbaje și compilatoare 52
(2) S
αwA
γαw
wy
(3) )y ( PRIM ) x ( PRIMk k=
implică . γ = β
O gramatic ă este de tip dacă ea este LL ()k LL pentru un anumit . k
Teorema 7.2. Fie o GIC . Atunci G este ( S , P , , N GΣ =) ()k LL dacă și
numai dac ă este adevă rată condiția : N A∈∀ astfel încât exist ă derivarea
și pentru orice α ⇒∗
wAS β→A și γ→A produc ții distincte, rezult ă
∅ = ∩ ) ( PRIM )k ( PRIMk γα βα
Demonstra ție.
,,
'' Fie o gramatic ă . Presupunem prin reducere la absurd c ă
astfel încât pentru orice deriva ție G
A∈ ∃) K ( LL
N S
αwA
() ()γ≠β∈γ→∃∈β→ ∃ A A , P ,P și ∅≠γα ∩βα ) PRIM ( PRIMk (k ) .
Fie ) ( PRIM ) ( PRIM uk k γα ∩βα ∈ ; rezultă ) ( PRIM ukβα ∈ , deci
βα
*xΣ ∈ și ) x ( PRIM uk=
și , deci ) ( PRIM ukγα ∈ γα
y∈Σ* și ) y ( PRIM uk= .
Am obținut
1) S
αwA
βαw
wx , *xΣ ∈
2) S
wAα
wγα
wy , y∈Σ*
3) ) y ( PRIM ) x ( PRIMk k=
și totuși ; deci gramatica nu este . Ajungem la o contradic ție , deci
presupunerea f ăcută este falsă. γ ≠ β ) k ( LL
,,
'' Presupunem prin absurd c ă nu este ; deci sunt adev ărate
condițiile 1) , 2) , 3) din defini ția 1.31 ș i totuși G ) K ( LL
γ≠β . Condiția 1) implic ă
existența derivației βα
*xΣ ∈ ; analog, 2) implic ă γα
*yΣ ∈. De aici
și din 3) ob ținem
) ( PRIM ) ( PRIM ) y ( PRIM ) x ( PRIMk k k k γα ∩βα ∈ = ,
deci , contradic ție. Rezult ă că presupunerea
făcută este fals ă, deci G este . ∅ ≠ γα ∩ βα ) ( PRIM ) ( PRIMk k
()k LL
Defini ția 7.4. Fie o GIC ; definim func ția , ( S , P , , N GΣ =) )( URMkβ
Definiția
gramaticii LL
Condiț ia
necesară și
suficientă ca o
gramatică să
fie LL
Automate, limbaje și compilatoare 53
unde este un întreg pozitiv iar k ()*NΣ ∪ ∈ β astfel:
{S w ) ( URMk= β
αβγ și }) (k PRIM wγ ∈ .
Vom da un algoritm care s ă verifice dac ă o gramatic ă este ,
deoarece teorema 7.2 este dificil de utilizat. ()k LL
Defini ția 7.5. Fie Σ un alfabet ș i . Definim
astfel încât *L , LΣ ⊆2 1
2 si 1 2 1 L y L x / w { L∈ ∃ ∈ ∃ = ⊕ Lk
a) xy w= dacă k xy≤ și
b) este format din primele simboluri din w k xy, în caz contrar }.
Ținând seama de defini ția de mai sus rezult ă ușor că
(). N , ) ( PRIM ) ( PRIM*
k k Σ ∪ ∈ ∀ ⊕ = β α α αβ ) ( PRIMk kβ
Acum, condi ția ca o gramatic ă să fie ()k LL
A ) ( se reformuleaz ă astfel : G este
dacă și numai dac ă (k LL) S ( , N∃∈∀
αwA ) astfel încât
()() γ≠β ∈γ→ ∀ ∈ β , P A , P →∀A implică
() ( )∅=⊕L )k ∩ ⊕ ( PRIM L ) ( PRIMk k k γ β , unde ) ( PRIM Lkα = .
Algoritmul TEST-LL – de testare a condi ției ()k LL
Intrare : o GIC și un număr întreg pozitiv ( S , P , , N GΣ =) k
Ieșire : ,,da“ dacă gramatica este ()k LL și ,,nu“ în caz contrar
Metoda :
Se consider ă că toate neterminalele sunt nemarcate.
Pasul 1. Pentru orice , nemarcat , pentru care exist ă cel puțin două N A∈ A –
producții distincte calculeaz ă
{ S L ) A (k *Σ ⊆ = σ
αwAși }) ( PRIM Lkα =
Pasul 2 . D a c ă și β → A γ→A sunt două A – produc ții distincte ,
calculează
() ( )L ) ( PRIM PRIM ) L ( fk k L ) (k k ⊕γ ∩⊕β =
pentru orice . Dacă ) A ( Lσ ∈ ∅≠) L (
) A ( Lf , răspunde ,,nu“ ș i oprește algoritmul.
Dacă pentru orice ∅ =) L ( f σ∈ , repetă pasul 2 pentru toate
perechile distincte de – producț ii și la sfârșit marcheaz ă pe . A A
Pasul 3. Repet ă pașii 1 și 2 pentru toate neterminalele nemarcate din . N
Pasul 4. Răspunde ,,da“ dacă toate neterminalele au fost marcate; în caz contrar
Algoritmul de
testare a condiției LL
Automate, limbaje și compilatoare 54
se merge la pasul 1.
Pentru a putea aplica aces t algoritm trebuie calculate func țiile și σ. k PRIM
Algoritmul PRIM. – de calculare a func ției PRIM
Intrare : o G I C k un num ăr întreg pozitiv și
( S , P , , N GΣ =
1)
()1 ≥ Σ ∪ ∈ = αn , N X … X*
n
Ieșire : ) (αk PRIM
Metoda : ținând seama de descompunerea
)( … ) ( ) (1 n k k k k k X PRIM X PRIM PRIM ⊕ ⊕ =α rezultă că este suficient s ă
calculăm cu ; dacă ) (x PRIMk N x∈ {}ε∪Σ∈x atunci {} = ) (x x PRIMk .
Calculăm recursiv mul țimile pentru Fxi() Σ∪∈N x și 0≥i
Pasul 1. {} {} 0≥ ∪ Σ ∈ ∀ =i , a : a ) a ( Fi ε
Pasul 2.
()
⎪⎭⎪⎬⎫
⎪⎩⎪⎨⎧
= < =∈ → Σ ∈=
ε αα
si k x fie k x fie undeP x A / x) A ( Fk *
0
Pasul 3. Presupunem c ă mulțimile au fost calculate pentru
orice . Atunci : 1 1 0 −iF …, , F , F
N A∈
() ⎭⎬⎫
⎩⎨⎧
∈ →⊕ ⊕ ∈∪ =− −
−P y y Ay F y F x xA F A F
nn i k k i
i i…, ) ( … ) ( /) ( ) (
11 1 1
1
Pasul 4. Dacă pentru N A∈∀ avem ) A ( F ) A ( Fi i=−1
se me luăm
) A ( F ) A ( PRIMi k= și oprim algoritmul; altfel rge la pasul 3.
Teorema 7.3. Algoritmul PRIM calculeaz ă corect valorile funcț iei
. k PRIM
Demonstra ție : Deoarece rezultă că mulțimile , cu
fixat și sunt în num ăr finit . Cum , există un
astfel încât F Apoi pentru orice k *
i) A ( FΣ ⊂ ) A ( Fi
A ,… , i1 0=
) A (n−1) A ( F ) A ( Fi i 1+⊂
nn
) A ( Fn= . j> a X ( vem Fn ) )X ( Fj= și
deci nF ste suficient s ă arătăm că PR U∞
==
0ii( F )) A. E A ( U∞
==
0ik) A ( IMiF ) A (.
,, ' ' F i e . Atunci, există un ⊂ ) A ( PRIM xk∈ r astfel încât A
y și
. Arătăm prin induc ție după )y ( PRIMk x= r că ) A ( Fr1− x∈ . Pentru 1=r este
trivial, deoarece . Să fixăm pe ) A ( F x0∈ r și să presupunem c ă ipoteza este
Calcularea valorilor funcției PRIM
Corectitudinea algoritmului PRIM
Automate, limbaje și compilatoare 55
verificată pentru valori mai mici decât r. Atunci A
nY … Y1
y unde
și ny … y y y2 1=pY
pentru py n p≤≤1 . Evident r rp< și conform
ipotezei de induc ție, . Obț inem )Y F ) PRIMi ir−∈ ( F )r i2−⊂Y (1 y (i k
() ()n kyk k… ) yk(ny …k PRIM yk( PRIM x PRIM ) yPRIM ⊕⊕ =1
) Y Fn k ⊂= =
( Fr2−1
) A (
Fr1− (r2− …k) Y1⊕⊕ ⊂
⊃.
,,'' Arătăm că prin inducț ie după ) A ( ) Ak⊂PRIM ( Fr r.
Pentru este evident. Presupunem afirma ția adevărată pentru valori mai mici
decât 0=r
r și să o demonstră m pentru r. Fie )A( F xr∈ ; dacă )A(1F xr−∈ rezultă
că , conform ipotezei de induc ție. )A (k PRIM x∈
Dacă ()P yp∈ ) … y1 A→ ș i )yp( Fr k1− … y ( Fr 1 1− xk⊕⊕ ∈ , avem
() )(A PRIMk …1y PRIMk ) ( y yp k…k)1(y PRIM xk PRIMk p⊂ = ⊕⊕ ∈
α.
Pentru ultima incluziune am folosit proprietatea urm ătoare
β implic ă ) (k PRIM) ( PRIMk α ⊂ β , a cărei demonstra ție este
evidentă.
Algoritmul URM1 – de calculare a func ției σ
Intrare : o GIC ()S , N
A∈ ∀, P ,Σ
NG și un număr întreg nenegativ =
pentru k
Ieșire : ) A ( σ
Metoda : Pentru calculăm NB∈, A∀
{ A( ,k∃ L L ) B , A (*Σ ⊂ = σ
}) și ) ( PRIMk L wB α α= Pentru aceasta construim
mulțimile )B , A (iσ pentru și N B∈, A∀ ,… ,1 0 i= astfel:
Pasul 1: fie (){ }) ș A / L ) (k= = σ0 ( PRIMk L i P wB∈ α B , A α →Σ ⊆
Pasul 2: presupunem că mul țimile ) B , A (i1−σ au fost calculate pentru orice
și definim astfel : N B , A∈ ) B
atunci L
→, A (iσ
B , A (a) dacă )B , A( ) ( Li i σ ∈ σ ⊂− 1
(b) dacă există producția și pentru un nX … X A1 j , n j≤≤1 , există o
mulțime , atunci include în ) B ( ' Li1−σ ∈ , Xj )B , A (iσ pe
()n j1+ k k X … X PRIM ' L L ⊕ =
Pasul 3: dacă pentru orice NB ,A∈ există un iastfel încât
) B, A ( ) B , A (i i 1−=σ σ luăm ) B , A (i ) B , A (σ σ= ; în caz contrar se merge la pasul
(2).
Calculul valorilor
funcției
σ
Automate, limbaje și compilatoare 56
Pasul 4: pentru orice ) A , S ( ) A ( N Aσσ= ∈ ia se .
Teorema 7.4. Algoritmul URM1 calculeaz ă corect valorile func ției σ.
Demonstra ție. Se arată c ă ) A ( Lσ∈ dacă și numai dac ă există
astfel încât (* *Nși w Σ ∪ ∈ α Σ ∈ ) S
) ( PRIM L i k ș wA α α= . Demonstra ția
este similar ă cu cea din teorema precedent ă.
Automate, limbaje și compilatoare 57
Teme Curs
Teste Autoevaluare
Testul 1
1. Considerăm gramatica {}{} () S , P , b , a , B , A , S G = cu produc țiile
, , , , , . Să s e
construiasc ă gramatica echivalent ă aflat ă în forma normal ă
Chomsky……………………………………………………………………………… 2 puncte aAB S→ BA S→ BBB A→ a A→ AS B→ b B→
2. Fie gramatica cu produc țiile
e / Sd / Ac A , b / Aa S → →
a) Să se arate c ă este recursiv ă la stânga……………………………….. 1 punct
b) Să se construiască o gramatic ă echivalent ă, fără recursie la
stânga…………………………………………………………………………… 2 puncte
3. Fie {} abb ,și {}bab , b L . Calculați
2 2 1L L⊕ …………..……………………………………………….1 .punct Lε =1 =2
4. Considerăm gramatica {}{} ( a , B , A , S G = )S , P , b , cu produc țiile
a / aB Bab / a AbAbB / aAaB S
→→→
Folosind defini țiile calcula ți și ) S ( PRIM3 ) A (σ ……….…….. 3 puncte
5. Oficiu ……………………………………………………………. 1 punct
TESTUL 2
Se consider ă gramatica {}{} ( S , P , b , a , B , A , S G = )
algoritmul să se calculeze valorile func ției cu produc țiile
a / aB Bab / a AbAbB / aAaB S
→→→
a) Folosind algoritmul PRIM, s ă se calculeze valorile func ției
3 PRIM ……………………………………………………………………… .3 puncte
b) Folosind σ σ.…….. .3 puncte
c) Să se verifice că gramatica este ) ( LL3 ……………………………………3 puncte
Oficiu………………………………………………………………….1 punct
Automate, limbaje și compilatoare 58
ăspunsuri la Testul 1
1. Gramatica R
{} {} () S , ' P , b , a , E , D , C , B , A , S ' G = cu produc țiile
'P={S→ BE A→ , BB E→ ,
a A→ B→ , b ormă normal ă Chomsk
echivalent ă cu G
2. a) Neterminalul CD
, , AB D→ , a C→ , BA S→ ,
AS B→} este în f y și este
S este recursiv la stânga deoarece S
Aa
Sda
b) Considerând c ă ordinea neterminalelor e , gramatica ste A , S
echivalent ă are produc țiile
→ b / Aa
ε →→
/ adA / cA AeA / bdA AS
' ' '' '
unde 'A este neterminal nou
3.
aspunsuri la Testul 2
a) }
b) }
c) , deci { L= ⊕1 }ab , ba , b L2 2
4. {} b , aaa PRIM bab , aa ) S ( =3
{} {{} baa , ba , aaa , aa ) A ( = σ }
R
{aaa ) S ( PRIM=3
{}
{} aaa , aa , a ) B ( PRIMab , a ) A ( PRIMbab , aab ,
==
33
{} {{}
{}{}ε = σ = σ= σ = σ∅ = σ = σ
) B , S ( ) B (baa , ba , aaa , aa ) A , S ( ) A () S , S ( ) S (
∅ = σ) S ( ∅=∅ = ) L ( f , L și se marcheaz ă
Pe lul S
ntru netermina A
}}
țiile {{ b aaa , aa ) A ( = σ} { baa , a ,
Pentru produc {}aaa , aa L și ab A , a A= → → avem
(){}{}∅=∩aba a =aa L f
pentru pro ducțiile i ab A , a A→ →ș{}baa , ba L= avem
{}{}∅=∩ =abb aba ) L ( f archeaz și se m ă S.
entru neterminalul P B:
{}{}ε= σ) B (
Automate, limbaje și compilatoare 59
țiile {}{}ε= → → Lși a B și , aB B pentru produc avem
{}{ }∅=a ∩ = aaa , aa ) L ( f inalul și se marcheaz ă neterm B
Rezumat: S-a echivalat o gramatic ă independent ă de context cu altele, utile
în anumite tipuri de analiz ă sintactic ă. S-a prezentat o metod ă de verificare a
faptului că o gramatic ă este sau nu de tipul LL .
Lucrari Practice (Laborator/Seminar)
onținut Laborator/Seminar
eme Laborator/Seminar
1. Să se scrie un program care sa construiasc ă forma normal ă Chomsky
IM
C
T
2. Să se implementeze algoritmul de eliminare a recursiei la stânga
3. Să se implementeze algoritmul de calculare a valorilor func ției PR
Rezumat: Se echivalează o gramatic ă independent ă de context cu
gramatici care vor simplifica analiza sintactic ă. Se implementeaz ă
algoritmul PRIM folosit la testarea condi ției LL .
Automate, limbaje și compilatoare 60
Notații
Automate, limbaje și compilatoare 61
Automate, limbaje și compilatoare 62
Automate, limbaje și compilatoare
63 Curs 5 Clase speciale de gramatici independente de context
(II)
Descriere Generală
Se defineș te noțiunea de gramatic ă LR apoi se demonstreaz ă condiția necesară
și suficient ă ca o gramatic ă să fie LR și se dă un algoritm de verificare.
Se definesc gramaticile de preceden ță simplă și slabă, relațiile de preceden ță
Wirth-Weber și se explic ă modul de construire a lor.
Obiective
– cunoașterea metodei de verificare c ă o gramatic ă este LR
– cunoașterea metodei de verificare că o gramatic ă este de preceden ță simplă
sau slabă
Cuprins
I.7.5. Gramatici LR(k)
I.7.6. Gramatici de preceden ță
Conținut Curs
I.7.5. Gramatici LR(k)
Gramaticile LR au fost introduse în 1965 de c ătre Knuth iar clasa
limbajelor generate de ele este clas a limbajelor independente de context
deterministe. Analiza prezintă avantajul generalit ății, toate limbajele de
programare ce accept ă o definiție sintactic ă fiind analizabile . LR
BNF LR
Pentru construirea arborelui de derivare se dispune de urm ătoarele
informații:
i o poziție inițială în cuvântul de an alizat pe care o notă m cu 1) p,
i întregul context stâ nga al cuvântului surs ă, adică , 2)pa … a a2 1
i următoarele simboluri ale sursei situate dup ă poziția 3) k p, adică
, k p pa …+ + 2 pa a+1Curs 5
Durata :
2 ore
Formularea
cerințelor LR
Automate, limbaje și compilatoare
64 i la fiecare pas, neterminalul care deriveaz ă este cel mai din dreapta . 4)
Gramatica G trebuie s ă aibă astfel de propriet ăți încât informa țiile
să ne asigure urm ătoarele: ) i ) i4 1−
1) dacă p indică sau nu limita dreapt ă a părții reductibile,
2) dacă p indică limita dreapt ă a părții reductibile atunci ) i ) i4 1− determin ă și
limita din stânga,
3) dacă a fost determinat ă partea reductibil ă, ) i ) i4 1− determin ă și producția ce
va fi utilizat ă pentru reducere.
Fie și . Pentru ) S , P , , N ( GΣ = ) G ( L w∈ N A∈ vrem să determin ăm
șirul m, … , ,ααα10 astfel încât: 0α=S
1α
…..
wm=α . Fie
și ; informa țiile Axαi= α−1 xiαβ = α ) i4) i1− trebuie s ă determine în mod unic
producția folosită în derivarea β → A1−αi
iα. În cazul gramaticilor
toate deriv ările sunt la dreapta; pentru simplificarea scrierii nu vom mai specifica
tipul deriv ării. LR
Cele de mai sus pot fi unificate sub forma conceptului formal de gramatic ă
. ) k ( LR
Defini ția 7.6. Fie o GIC. Se nume ște gramatic ă extinsă a
lui G, gramatica unde ) S , P , , N ( GΣ =
S { P , }, ' S {∪ Σ ∪ ) ' S }, S ' N ( ' G → = N ' S∉. Producția
o vom numerota cu 0 iar celelalte cu 1, 2, … ,S ' S→ p.
Defini ția 7.7.
Fie o GIC și ) S , P , , N ( GΣ = ) ' S , ' P , , ' N ( ' GΣ= gramatica
sa extinsă. este , , dacă: G ) 0≥kk ( LR
1) ' S
Awα
wαβ
2) ' S
Bxγ
y xαβ=γδ
3) )y ( PRIM ) w ( PRIMk k=
implică BxAyγ= α (adică B A ,=γ= α și yx=).
Defini ția 7.8. Cuvântul este un prefix viabil în gramatica
dacă *) N (Σ ∪ ∈γ
) S , P , , N ( GΣ = S
Awα
wαβ și γ este un prefix al lui αβ; αβ
se numește parte deschis ă.
Definiția
gramaticii de
tip LR
Defini ția 7.9. Fie o GIC. Vom spune c ă )S , P , , N ( GΣ = ] u , . A [2 1ββ→
este linie , dacă ) k ( LR P ) A (∈→2 1ββ și . k *uΣ ∈21ββ. A→ se nume ște
nucleul iar u șirul de anticipare al liniei.
Defini ția 7.10.
Linia ) k ( LR ] u , . A [2 1ββ→ este valid ă pentru prefixul
viabil 1αβ dacă există o derivare de forma S
Awα
w2 1βαβ și
. ) w u= ( PRIMk
Exemplul 7.2. Fie gramatica cu produc țiile:
D / C S→
b / aC C→
c / aD D→
Linia este valid ă pentru aaa deoarece exist ă derivația [ ε →, C . a C
Automate, limbaje și compilatoare
65 ] S
aaC
aaaC = α cu și . aa ε =w
Defini ția 7.11. Funcția ( → Σ ∪*) N ( : EFF ) ( P*
fΣε-free first) este o
restricț ie a funcției PRIM și este definit ă astfel:
*
k k ) N ( N dac ) ( PRIM ) ( EFFΣ ∪ ∉ α α = α ă și
α = α/ w { ) ( EFFk
()wx PRIM w , wxk= și ultima producț ie folosită nu este
ε−producție când ()*N NΣ ∪∈ α
Exemplul 7.3. Pentru gramatica G cu produc țiile
ε →→ε →→
/ c CC / Cb B/ Ba AAB S
avem , } cb , ca , ba , ac , ab , c , b , a , { ) S ( PRIM ε =2 } cb , ca { ) S ( EFF=2 .
Lema 7.1. Fie o gramatică extinsă care nu este LR(k).
Atunci: ) ' S , P , , N ( GΣ =
1) ' S
Awα
wαβ
2) ' S
Bxγ
y xαβ = γδ
3) )y ( PRIM ) w ( PRIMk k=
4) γδ ≤ αβ
implică . Bx Ayγ ≠ α
Demonstra ție. Din defini ția gramaticii deducem că pot fi
satisfăcute toate condiț iile din lem ă exceptând ) k ( LR
γδ ≤ αβ. Presupunând γδ > αβ
se ajunge la contradic ția . Bx Ayγ = α
Teorema 7.5. O gramatic ă ) S , P , , N ( GΣ= este dacă și numai
dacă este îndeplinit ă urmă toarea condi ție, pentru orice : dacă )k (LR
k *Σ ∈u []u ., Aβ→
este linie validă pentru prefixul viabil )k (LR αβ atunci nu exist ă nici-o alt ă
linie [
Automate, limbaje și compilatoare
66 ]v , .2 1 A1ββ→ validă pentru cu αβ )v2( EFF ukβ∈ .
Demonstra ție.
""⇒ Presupunem prin absurd c ă și există prefixul viabil k *uΣ ∈ ∃ αβ astfel încât
[] u ., Aβ→ și [ v , . A2 1 1]ββ→ sunt două linii valide pentru prefixul .
Înseamnă că: αβ
' S
Awα
wαβ cu ) w ( PRIM uk=
' S
x A1 1α
x2 1 1ββα cu ) x ( PRIM vk=
și 1 1βααβ= . În plus, x2β
) v ( EFF u , uyk 2β∈ .
Cazul I . Dacă εβ=2 atunci și v u=
' S
Awα
wαβ
' S
x A1 1α
x1 1βα
v u ) x ( PRIM ) w ( PRIMk k == = .
Deoarece cele dou ă linii sunt distincte, înseamn ă că fie ) k ( LR1A A≠, fie
1ββ≠. În plus, x1A Ax1α≠ α , deci G nu este . ) k ( LR
Cazul II . Dacă atunci +Σ ∈ =z2β
' S
Awα
wαβ , ) w ( PRIM uk=
' S
x A1 1α
zx1 1βα , ) x ( PRIM vk=
) w ( PRIM ) zx ( PRIMk k=
În acest caz G nu poate fi deoarece ) k ( LR x A Azx1 1α≠α .
Cazul III . Presupunem că 2β conț ine cel pu țin un simbol neterminal. Atunci
Condiț ia
necesară și
suficientă ca o
gramatică să
fie LR
2β
3 1Bu u
3 2 1u u u unde ε≠2 1u u , deoarece conform defini ției,
) v ( EFF uk 2β ∈ și prin urmare un simbol neterminal de început nu poate fi
înlocuit prin cuvântul vid. Astfel, avem deriva țiile:
' S
Awα
wαβ
' S
x A1 1α
x2 1 1β βα
x Bu u3 1 1 1βα
x u u u3 2 1 1 1βα = x u u u3 2 1αβ
cu . Deci uy x u u u=3 2 1 u ) x u u u ( PRIM ) w ( PRIMk k = =3 2 1 .
Deoarece gramatica este rezultă că ) k ( LR x Bu u x u u Au3 1 1 1 3 2 1βα= α , adică
, egalitate imposibil ă deoarece u . B u u Au1 1 2 1β =+Σ ∈2u1
""⇐ Presupunem c ă G nu este . Atunci avem ) k ( LR
' S
Awα
wαβ
' S
Bxγ
y xαβ=γδ
) y ( PRIM ) w ( PRIMk k= =u
dar . Putem alege deriv ările astfel încât Bx Ayγ ≠ α αβ să aibă lungimea cât mai
mică posibil. Ținând seama de lema 7.1 presupunem c ă γδ αβ≤ . Notăm cu
ultima form ă derivațională la dreapta în derivarea 1 1y A1α ' S
Bxγ astfel încât
lungimea p ărții sale deschise nu dep ășește 1+αβ , adică
Automate, limbaje și compilatoare
67 11+ ≤αβ1αA .
Derivarea de mai sus se poate scrie
' S
1 1 1y Aα
1 2 1 1yββα
y1 1βα
cu αββα=1 1 . Din alegerea lui 1 1 1y Aα avem γδ αβ α≤ ≤1 . În plus, în derivarea
1y2β
y nu se foloseș te ca ultim ă producție o ε-producție, că ci dacă
ar fi ultima producț ie folosită atunci ε → B
1 1y A1α nu ar fi ultima form ă derivațională la
dreapta în derivarea ' S
Bxγ a că rei parte deschis ă nu depășe ște în lungime
1+αβ . Astfel, ) y PRIM u1 (k 2 EFF ) y (k β∈ = . Rezultă că [ ]v ,. A2 1 1ββ→ este
linie validă pentru , unde )k ( LR αβ ) y1( PRIMvk= .
Din ' S
Awα
wαβ deducem c ă []u ., Aβ→ este linie valid ă pentru . Să
arătăm acum c ă liniile αβ
[]u ., Aβ→ și [ ] A v , .2 1 1ββ→
2 sunt distincte. Pentru aceasta
presupunem contrariul; deci 1 1ββ. A→ coincide cu . Aβ→ Atunci, ultima
derivare de mai sus este de forma
' S
Ay1α
yβα1
cu αββα=1 . Atunci α =α1 și Bx Ayγ=α , contrar ipotezei c ă nu este G
Automate, limbaje și compilatoare
68 ) k ( LR.
Fie G o GIC ș i γ un prefix viabil. Not ăm cu mulțimea liniilor
LR(k) valide pentru prefixul viabil . Vom renunț a să mai specific ăm pe k și G
dacă acestea se subîn țeleg. ) ( VG
kγ
γ
Algoritmul LINII-LR – de calculare a mul țimilor kV
Intrare: o GIC, și n )S , P , , N ( GΣ =*
n ) N ( x … x xΣ ∪ ∈ = γ2 1 ≥0
Ieșire: ) (G
kγ V
Metoda: Se calculeaz ă succesiv
) x … x x ( V …, ), x x ( V ), x ( V ), ( VnG
kG
kG
kG
k 2 1 2 1 1ε
Pasul 1. Se construie ște mulțimea ) ( VG
kε
(a) Dacă P ) S (∈ →α , se include în linia ) ( VG
kε[]εα→ , . S
(b) Dacă și [] ) ( V u , B . AG
kε β∈ →2 P ) B (∈→β , atunci pentru
) u ( PRIM xk 2β ∈ ∀ se include în ()εG
kV linia []x , . Bβ→ , dacă nu a fost deja
inclusă.
(c) Se repet ă pasul 1.b pân ă când nici-o linie nu mai poate fi ad ăugată la
. ) ( VG
kε
Pasul 2. Presupunem c ă a fost calculat ă mulțimea ()1 2 1−iG
k x … x x V și calculăm
astfel: ) x … x x ( ViG
k 2 1
(a) Dacă atunci se include în [] ) x … x x ( V v , x . AiG
k i 1 2 1 2 1 − ∈ β β → ()iG
k x … x V1 linia
. [] v , .2βx Ai1β →
(b) Dacă și [] ) x … x ( V u , B . AiG
k 1 2 1∈ →β β ()P B∈→β atunci se include în
linia [] ()ix x , . BG
k … x x V2 1 β→ x pentru ) u ( PRIMk 2β ∈∀ , dacă aceasta nu a fost
deja inclusă .
(c) Se repet ă pasul (2.b) până când nu se mai poate ad ăuga nici-o linie la
mulțimea . ()iG
k x … x x V2 1
Definiția 7.12. Fie gramatica )S , P , , N ( GΣ= și 0≥k
A , unde . Definim func ția GOTO astfel: ()γ =G
kV*) N (Σ ∪ ∈ γ
GOTO(A , x)=A’, unde A'()x VG
kγ = și Σ∪∈N x .
Calcularea
liniilor LR
Automate, limbaje și compilatoare
69 Urm ătorul algoritm d ă o metodă sistematic ă de calculare a mul țimii de
linii . ) k ( LR
Algoritmul COLEC ȚIE
Intrare: GIC ) S , P , , N ( GΣ= și k≥0, număr de intrare
Ieșire: S ={ A/A()γ ∈G
kV și este prefix viabil al lui G } γ
Metoda : Inițial S =∅
Pasul 1. Se include în S mul țimea nemarcată . ) ( VG
kε
Pasul 2. Dacă A∈S este nemarcat ă, atunci se marchează Adupă ce se
calculează pentru fiecare mulțimea A ’ = GOTO(A, x). Dacă A’
și nu există deja în S atunci se adug ă A’ la S, nemarcată . Σ ∪ ∈N x ∅ ≠
Pasul 3. Se repet ă pasul (2) pân ă când toate elementele lui S sunt marcate.
Mul țimea S se nume ște colecția canonic ă de mulțimi de linii ,
pentru gramatica G. ) k ( LR
Definiția 7.13. Fie o GIC și k un num ăr întreg nenegativ.
O mulțime A de linii se numește consistent ă dacă nu conț ine două linii
de forma )S , P , , N ( GΣ =
)k(LR
] u ., A [β→ și ] v , . B2 1 [ββ→ cu )v ( EFF uk 2β∈ .
Din aceast ă definiție și din teorema 7.5 rezult ă următorul algoritm de
testare a condi ției . ) k ( LR
Algoritmul TESTARE-LR
Intrare: o GIC și un număr întreg ) S , P , , N ( GΣ = 0≥k
Ieșire : "DA" dac ă G este și "NU" în caz contrar ) k ( LR
Metoda
Pasul 1. Utilizând algoritmul COLECTIE se calculeaz ă colecț ia canonic ă de
mulțimi de linii . ) k ( LR
Pasul 2. Se examinează fiecare mul țime de linii LRk() din S și se determin ă
dacă este consistent ă.
Pasul 3. Dacă toate mulț imile din S sunt consistente se r ăspunde "DA"; în caz
contrar se r ăspunde "NU".
Testare
condiție LR
I.7.6. Gramatici de preceden ță
Așa cum am v ăzut anterior, dac ă gramatica este , determinarea
capătului din dreapta al p ărții reductibile se face cu ajutorul unei func ții asupra
următoarelor k simboluri din por țiunea neexplorat ă a cuvântului de intrare. Adic ă,
dacă este dată derivarea , atunci determinarea lui G ) k ( LR
w w A S*αβ α⇒ ⇒ β se face cu
ajutorul unei funcț ii asupra cuvântului )( PRIMkβ. Conceptul de gramatic ă de
precedență este legat de existen ța unor rela ții (numite de preceden ță) între
simbolurile lui Σ∪N
w z y 'β α, care permit izolarea p ărții reductibile. Dac ă
cu ' y ' w w A S
d*
dαβ α= ⇒ ⇒ ββ= și ' zw w= , atunci izolarea cap ătului din
dreapta a lui β rezultă din:
1) toate simbolurile consecutive ale lui β satisfac o anumit ă relaț ie
2) ultimul simbol al lui β și primul simbol al lui , adică perechea ,
satisfac o alt ă relație. w (z , y
Automate, limbaje și compilatoare
70 )
Deci, izolarea p ărții reductibile depinde numai de rela ția în care se g ăsesc
două simboluri succesive. Rela țiile, trei la num ăr, sunt notate de obicei cu
. În cazul preceden ței simple, într-o derivare dreapt ă de forma: <⋅ = ⋅>⋅, ,
x a X X X x a A X Sk kdk*
d1 1 1 K+ +α ⇒ α ⇒
porțiunea este delimitat ă prin cele trei rela ții astfel: 1 2X X XkK
– la dreapta: 1 1a X> ⋅
– la stânga: k k X X⋅ <+1
– în interior: pentru i iX X⋅
+=1 k , , i1 1−=K .
De asemenea, între simbolurile consecutive din 1+αkX , avem rela ția
sau . Facem observa ția că toate deriv ările sunt la dreapta. ⋅ <
⋅=
Defini ția 7.14. Fiind dat ă o GIC )S , P , , N ( GΣ= se numesc rela ții de
precedență Wirth-Weber rela țiile definite pentru > ⋅ = ⋅ <⋅,, Σ∪∈N Y , X și
astfel: Σ ∈a
(1) YX⋅< dacă există producția 2 1ββXB C→ și α ⇒+YB
(2) YX⋅= dacă există producția 2 1ββXY C→
(3) X ⋅> dacă există producția a2 1ββAB C→ și A⇒+Xα, βa B*⇒
La acestea se adaug ă relațiile ce implic ă marcajul $, de început și sfârș it al
cuvântului de intrare:
(4) dacă X $⋅ < α ⇒+X S
(5) dacă . $ X> ⋅
Automate, limbaje și compilatoare
71 X Sα ⇒+
Defini ția 7.15. O GIC )S , P , , N ( GΣ= este proprie dac ă:
(1) nu are simboluri inutile
(2) nu exist ă cicluri, adic ă derivă ri de forma A A+⇒
(3) nu are ε-producții în afara, eventual, a produc ției ε→S , caz în care nu
apare în membrul drept al nici unei produc ții. S
Defini ția 7.16. O GIC proprie, f ără ε-producții, în care între oricare
două simboluri exist ă cel mult o rela ție de preceden ță Wirth-Weber se nume ște
gramatică de preceden ță. Dacă , în plus, gramatica este și unic invertibil ă, ea se
numește de preceden ță simplă.
Lema 7.2. Fie o gramatic ă proprie f ără ε-producții. ) S , P , , N ( GΣ =
(1) Dacă Y X⋅ < sau YX⋅= și P ) A Y (∈α→ atunci A X⋅<.
(2) Dacă sau a X⋅ < YX⋅= sau și a X> ⋅ P) Y X (∈α→ atunci a Y>⋅.
Demonstra ție. Demonstr ăm (1). Dac ă Y X⋅< atunci P ) XB C (∈ →2 1ββ
și ; deci . Din γ⇒+Y B γα ⇒γ⇒+A Y B P ) C ( XB∈ →2 1ββ și rezultă γα ⇒+A B
A X⋅ <. Dacă YX⋅= C ( atunci P) XY∈ →1 2ββ ; ținând seama și de faptul c ă
rezultă P∈) Aα → Y ( A X⋅ <. Punctul (2) se demonstreaz ă similar.
Teorema 7.6. Fie )S , P , , N ( GΣ= o gramatic ă proprie f ără ε-
producții și derivarea:
q k k p p q k p p a a X X X X X a Aa X X X $ S $K K K K K1 1 1 1 1 1 1 + − + −∗
⇒ ⇒
Atunci:
(1) pentru avem sau pi k< <i i X X⋅ <+1 i iX X⋅
+=1
Relațiile de
precedență
Automate, limbaje și compilatoare
72 (2) k k X X⋅ <+1
(3) pentru i iX X , k i⋅
+= − ≤ ≤1 1 1
(4) . 1 1a X> ⋅
Demonstra ție. Folosim inducț ia după numărul al pașilor în care are loc
derivarea indirect ă. Pentru avem și conform
definiției 7.14 avem pentru 1n
⇒
10=n
⋅=iX X ,$ X X $ $ S $ $ S $k 10L ⇒
1+ ⋅ <i kX $ −≤≤ k i $ X> și ⋅1 .
1X XkL
− nu poate fi cuvânt vid deoarece gramatica este presupus ă fără
εproducții. Presupunem c ă afirmaț ia din teorem ă este adev ărată pentru n și fie
derivația:
q k pna Aa X X $ S $L L1 1+ ⇒q k k p a a X X X XL L L1 1 1+ ⇒
q j r j p a a X X Y Y X XL L L L1 1 1 1 1 − + ⇒
unde la ultimul pas, a fost înlocuit cu , deci
sunt terminale (dac ă 1 atunci ) p j ( Xj≤ ≤ 1
=j1Y YrL1 1 X , , XjL−
ε=− 1 1X XjL ). Conform ipotezei inductive,
sau ș i din lema 1.2. rezult ă j j X X⋅ <+1 j jX⋅
+=1XrYjX⋅<+1 . Apoi,
, deoarece este membrul drept al unei reguli. Între și
(sau a) există una dintre cele trei rela ții posibile; confor m punctului (2) al
lemei 1.2 avem Y sau dacă 1Y⋅=
11Y Yr r⋅
−⋅= =L
1−jX1Y YrL
1−jX Y> ⋅1jX
1> ⋅ a 1=j. De asemenea, i i X⋅ X<+1 sau
pentru i iX X⋅
+=1 pij<< , conform ipotezei de induc ție.
Corolarul 7.1. Dacă G este gramatic ă de preceden ță, atunci concluziile
teoremei 7.6 devin:
(1) pentru , fie , fie ; p i k< <i i X X⋅ <+1 i iX X⋅
+=1
(2) ; k k X X⋅ <+1
(3) pentru ; i iX X , k i⋅
+= − ≤ ≤1 1 1
(4) ; 1 1a X> ⋅
(5) între oricare dou ă simboluri din șirul nu mai există nici-o alt ă
relație în afara celor precizate în (1)-(4). 1 1a X XpL
Plecând de la defini ția 7.14, vom da un algor itm de calculare a rela țiilor
Corectitudinea
relațiilor de
precedență
Automate, limbaje și compilatoare
73 Wirth-Weber. Îl vom explica pe exemplul urm ător.
Exemplul 7.4 . Fie gramatica cu producț iile:
a Sa A bAAc S| ,→ →
Ne propunem s ă determin ăm relațiile Wirth-Weber. Fie , , mulțimea
perechilor ce se afl ă respectiv în rela ția . Mulțimea se determin ă
căutând în partea dreapt ă a produc⋅=M> ⋅M
M⋅ <M
⋅==⋅ >< ⋅⋅,,
țiilor, toate perechile de simboluri consecutive;
obținem . Pentru a calcula mulț imea se
pornește cu ea vid ă și cu o mulț ime M iniț ializată cu . Se caută în M perechi
de forma cu )} a , S ( ), c , A ( ), A , A ( ), A , b {( =⋅=M
) B , X ( N B⋅ <M
⋅=M
∈; în exemplul nostru ele sunt și . Pentru
fiecare ) A, b ( )A , A (
B din aceste perechi c ăutăm în membrul drept al −Bproducțiilor primul
simbol; fie el Y. Se adaug ă la mulțimea și dacă Y ) Y , X (⋅ <M N∈ se adaugă și
la M. În exemplul nostru, din obținem și . Ambele se adaug ă
la iar se adaugă și la M. Calcularea lui se încheie când nu mai
există în M nici-o pereche netratată. În final se adaug ă perechile
unde ; în cazul nostru, . Ob ținem
. Pentru a calcula mulț imea
, o consider ăm inițial vidă. Fie M o mul țime inițializată cu . În M c ăutăm
perechi de forma ) A , b (
) S , b (
) B , X (
γ ⇒+Y S
( ), S , A ( ), a , A ( ), b , b ( ), S , b ( ), a ,
N A ), B , A () a , b (
)} b ($, ), b , A)
) b ($,
MS , b (
⋅ ⋅ <M
=⋅ <
> ⋅<M
) Y($,
b {( M
M⋅=
∈ cu
). a , S ( ), c , A PRIM; în exemplul nostru ele sunt
Se calculeaz ă , apoi pentru fiecare ( ),A , A( ) B (1 −Aproducție
se ia ultimul simbol al p ărții drepte, fie el X. Se adaugă la toate perechile
, iar la mulț imea M perechile (> ⋅M
a , X ) B ( PRIM a1∈ ) a , X ( cu NX )∈ cu . În
exemplul nostru, pentru avem ) A , A ( } b, a{) A ( PRIM=1
( ), c , a ( ), b ,, iar ultimul simbol al
părții drepte este . Deci perechile adăugate la sunt: și .
Mulțimea rezultat ă este: . Tabelul rela țiilor
de preceden ță este prezentat mai jos. a
a ( ), a , a {( => ⋅M> ⋅M
a) a ,a (
$)}) b, a (
, c ( ), , c
Condiția ca rela țiile de preceden ță definite pentru o GIC s ă fie disjuncte
este destul de tare. Dac ă se impune numai condiț ia de disjunc ție care asigur ă
izolarea corect ă a cap ătului din dreapta al p ărții reductibile, adic ă
Construirea relațiilor de
precedență
∅ = = ∪ ⋅ < ∩ > ⋅⋅) ( , se obț ine o gramatic ă de preceden ță slabă.
S A a b c $
S = ⋅
A <⋅ = ⋅ <⋅ <⋅ =⋅
a ⋅> ⋅> ⋅>
b <⋅ =⋅ <⋅ <⋅
c ⋅> ⋅
Automate, limbaje și compilatoare
74 >
$ <⋅
Defini ția 7.17 . O gramatic ă , proprie și fără G ε-producții, se nume ște
de preceden ță slabă dac ă:
(1) ∅ = = ∪ ⋅ < ∩ > ⋅⋅) (
(2) dac ă și sunt produc ții ale lui G, atunci nici una din
relațiile β α →X A β → B
B X⋅ <, BX⋅= nu este validă .
Automate, limbaje și compilatoare
75
Teme Curs
Teste Autoevaluare
1. Considerăm gramatica ) E , P }, , cu produc țiile
0 1aE E și , b , a { }, E ({ G1 0 =
E→ E b→ . Se cere
a) Să se construiască colec ția canonică de linii ) ( LR1……..….. 4 puncte
b) Să se verifice că gramatica este ) ( LR1………………………… … 2 puncte
2. Fie gramatica cu produc țiile:
a / ) E ( FF / F *T TT / T / T E E
→→+ + →
a) Să se construiască matricea rela țiilor de preceden ță simplă….. 2 puncte
b) Să se verifice că gramatica este de preceden ță slabă……………. 1 punct
Oficiu…………………………………………………………………………………………… 1 punct
Răspunsuri
1. a)
]} / , b . E [ ], / , aE E . E [ ], , E . ' E {[ ) ( V1 1 0 1 A0 1 ε→ε → ε → = = ε
]} / , aE . E E [ ], ., E ' E {[ ) E ( V ) E , ( GOTO1 0 1 A A1 1 0 ε →ε→ = ==
]} / ., b E {[ ) b ( V ) b , ( GOTO1 A A2 1 0 ε→ = ==
]} / , aE . E E {[ ) E ( V ) , ( GOTO1 0 1 A 1 1 A3 1 1 ε → = ==
4 1 3 A 1 A = =) a E ( V ) a , ( GOTO
. E [ ], / , E . a E E {[ 1 0 1→ ε → = ]} / , b . E [ ], / , aE E1 0 1 0 0 1→
= = =5 1 4 A 1 A ) aE E ( V ) E , ( GOTO[] [ ] {} 1 0 0 1 1 0 1, aE . E E , , . aE E E →ε →
]} / ., b E {[ ) ab E ( V ) b , ( GOTOA 1 A6 1 4 = = = 1 0→
= = =7 1 5 A 0 1 0 A) aE E ( V ) , ( GOTO ]} / ., aE E E {[1 0 1ε →
= = =8 1 5 A 1 1 1 A) aE E ( V ) , ( GOTO ]} / , aE . E E {[1 0 0 1 →
= = =9 1 8 A 1 1 A ) a aE E ( V ) a , ( GOTO
, aE E . E [ ], / , E . a E E {[0 0 1 1 0 0 1→ → ]} / , b . E [ ], /1 0 1→ .
) aE aE E ( V ) E , ( GOTO1 1 A1 9=
]} / , aE . E E [ ], / , . aE E E {[1 0 0 1 1 0 0 1 A10 → → = =
6 9 A A=) b , ( GOTO
]} / ., aE E E {[ ) aE aE E ( V ) , ( GOTO1 0 0 1 A 0 1 1 0 A11 1 10 →== =
8 10 A 1 A=) , ( GOTO
Colecția canonică este . } …, , , {11 1 0A A A S =
b)
Mulțimea este consistent ă deoarece nu con ține linii de forma 0A ] u ., A [β→ .
Mulțimea ]} / , aE . E E [ ], ., E ' E {[1 0 1 A1 ε → ε → =
ε ) aE ( EFF }, , { v , aE0 1 1 0 11 2 conț ine linii de ambele forme.
Deoarece , =u } {1= ε ∈ = β , } { ) aE1 01 ( EFF11= și
rezultă că această linie este consistent ă. } {1∉ ε
La fel se arat ă că toate liniile sunt consistente ș i deci gramatica este ) ( LR1.
2. a)
E T F a ( ) + * $
E =⋅ =⋅
T ⋅
Automate, limbaje și compilatoare
76 > ⋅> =⋅ ⋅>
F ⋅> ⋅> ⋅> ⋅>
a ⋅> ⋅> ⋅> ⋅>
) ⋅> ⋅> ⋅> ⋅>
( <⋅ <⋅
,= ⋅ <⋅ <⋅
<⋅
<⋅
+ <⋅⋅,= <⋅ <⋅ <⋅
* =⋅ <⋅ <⋅
$ <⋅ <⋅ <⋅ <⋅ <⋅ <
Automate, limbaje și compilatoare
77 ⋅
b) Condiția (1) din defini ția 1.40 este satisf ăcută. Verificăm condi ția (2).
Considerăm produc țiile
T E , T E E+→ + →
*T T→și ; deoarece nu exist ă relații
de preceden ță între E și E și nici între + și E rezultă că este satisf ăcută condiția
(2). Consider ăm acum produc țiile și ; deoarece nu exist ă
relații de preceden ță între * și T, condiția (2) este din nou verificat ă. Deoarece nu
mai sunt reguli care s ă aibă ca sufix al p ărții drepte partea dreaptă a unei alte
reguli, înseamn ă că gramatica este de preceden ță slabă. T E→
T→ F F
Rezumat: S-au definit gramaticile LR și cele de preceden ță, s-au dat o
metodă de verificare c ă o gramatic ă este LR ș i un algoritm de construire a
relațiilor de preceden ță.
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Calcularea rela țiilor de preceden ță simplă
Teme Laborator/Seminar
1. Să se scrie un program care să calculeze rela țiile de preceden ță simplă
Automate, limbaje și compilatoare
78
Rezumat: Se calculează relațiile de preceden ță Wirth-Weber
Automate, limbaje și compilatoare
79 Notații
Automate, limbaje și compilatoare
80
Automate, limbaje și compilatoare
81
II. PROIECTAREA COMPILATOARELOR
Curs 6 Teoria traducerii. Analiza lexical ă
Descriere Generală
Se analizeaz ă metode de traducere a limbajelor și se prezint ă principiile de
realizare a analizei lexicale.
Obiective
– cunoa șterea etapelor ce trebuie parcurse în vederea proiect ării unui
compilator
– cunoașterea principalelor tehnici de traducere a limbajelor
– însuș irea metodologiei de proiecta re a unui analizor lexical
Cuprins
II.1.1. Structura unui compilator
II.1.2. Traduc ătoare
II.1.2.1 Scheme de traducere orientate de sintax ă
II.1.2.2. Traduc ătoare finite
II.1.2.3. Traduc ătoare pushdown
II.2. Analiza lexical ă
II. 2.1. Generalit ăți
II. 2.2. Proiectar ea unui analizor lexical
Conținut Curs
II. 1. TEORIA TRADUCERII
II.1.1. Structura unui compilator
Compilatorul traduce un program scris în limbaj de nivel înalt
(FORTRAN, PASCAL, C, C++, JAVA, etc.) în limbaj maș ină.
Deci un compilator prime ște la intrare un program surs ă și furnizeaz ă la Curs 6
Durata :
2 ore
Automate, limbaje și compilatoare
82 ieșire un program obiect echivalent (ex ecutabil, translatabil, limbaj ma șină, etc.)
și un fișier de erori. Traducerea programelor surs ă în program obiect se face în
mai multe faze, a șa cum rezult ă din figura 1.1.
Figura 1.1
1. Analiza lexical ă grupează caracterele programului în sub șiruri, numite
atomi lexicali, care reprezint ă : cuvinte cheie, operatori, constante, identificatori.
De exemplu, în instruc țiunea de atribuire
60∗+= ratia valinit : valfin (1)
analiza lexical ă depisteaz ă următorii atomi lexicali:
– identificatorul valfin
– simbolul de atribuire : =
– identificatorul valinit
– operatorul de adunare + – identificatorul
rația
– operatorul de multiplicare ∗
– constanta numeric ă 60.
Spa țiile ce separă atomii lexicali sunt eliminate în timpul analizei lexicale.
Vom utiliza și pentru valfin , valinit și rația, respectiv, pentru a
sublinia că reprezentarea internă a unui identificator este diferit ă de secven ța de
caractere ce formeaz ă identificatorul. Reprezentarea intern ă a instruc țiunii (1)
după analiza lexical ă este : 2 1id , id3id
Schema
generală a
unui compilator
Explicarea rolului fiecă rei
etape de realizare a unui
Automate, limbaje și compilatoare
83 . id id : id603 2 1∗+=
2. Analiza sintactic ă. Șirul de atomi lexicali este preluat de analiza
sintactică; ea depisteaz ă în șirul atomilor lexicali struct uri sintactice ca: expresii,
liste, instruc țiuni, proceduri, plasându-le în ar borele sintactic (figura 1.2) ce
descrie rela țiile de incluziune a structurilor sintactice unele în altele:
Figura 1.2
3. Analiza semantic ă. Scopul analizei semantice este de a îmbog ăți
arborele sintactic prin inserarea de informa ții suplimentare în tabela de simboluri
și de a conduce generarea codu lui intermediar. O component ă importantă a
analizei semantice este verifica rea tipurilor. Reprezentarea intern ă a unui num ăr
real este în general diferit ă de cea a unui num ăr întreg chiar dac ă ele au aceea și
valoare. Presupunem, de exemplu, c ă toți identificatorii din figura 1.3 au fost
declaraț i reali. Opera ția ∗ se aplică unui num ăr real rația și unui num ăr întreg 60;
are loc conversia tipului întreg la real. Aceasta se realizeaz ă prin inserarea unui
nod suplimentar int-in-real .
Figura 1.3 compilator
Automate, limbaje și compilatoare
84
4. Generarea codului intermediar . Codul intermediar este de obicei, un șir
de instrucț iuni simple cu format fix. Opera țiile lor se apropie de opera țiile
calculatorului, iar ordinea lor respect ă ordinea execu ției. Operanzii instruc țiunilor
sunt însă variabile din program sa u introduse de compilator și nu regi ștri ai
calculatorului. De exemplu, arborele semantic din figura 1.3 se traduce în:
. t : idt id : tt id : t) ( real – in – int : t
3 12 2 31 3 21 60
=+ =∗ ==
5. Optimizarea codului . În faza de optimizare de cod se elimin ă
redundanțele, calculele și variabilele inutile, pentru a realiza o execu ție mai
eficientă:
. t id : id. * id : t
1 2 13 1 0 60
+ ==
6. Generarea codului . În aceast ă fază se selecteaz ă locațiile de memorie
pentru fiecare variabil ă din program și se translateaz ă codul intermediar într-o
secvență de instrucț iuni mașină. Un aspect important const ă în alocarea de regi ști
pentru variabile:
r2 , id MOV3
# MUL r2 60.0,
r1 , id MOV2
r1 r2, ADD
1id r1, MOV
7. Gestiunea tabelei de simboluri . O funcție esențială a compilatorului
este de a înregistra identificatorii utiliza ți în programul surs ă și de a colecta
informații despre diferitele atribute asociate variabilelor. Atributele furnizeaz ă
informații despre memoria alocat ă pentru un identificator, tipul s ău, numărul și
tipul parametrilor unei proceduri, modul de transmitere a fiecărui argument. O
tabelă de simboluri este o structur ă de date con ținând o înregistrare pentru fiecare
identificator, cu câmpuri pentru atribute.
Tabela de simboluri
1 Valfin ……..
2 Valinit …….
3 Rația …….
4
8. Tratarea erorilor este o colec ție de proceduri ce sunt activate ori de
câte ori se depisteaz ă o greșeală în program. În acest caz utilizatorul trebuie s ă
primească un mesaj de eroare iar compilarea s ă continuie m ăcar cu faza de
analiză sintactic ă (în cadrul programului gre șit ) pentru a detecta și alte eventuale
erori.
II.1.2. Traduc ătoare
Așa cum am precizat anterior, rolul compilatorului este de a traduce
programul surs ă în program obiect. Traducerea se face în mai multe faze: analiza
lexicală , analiza sintactic ă, etc., fiecare faz ă fiind la rândul s ău o traducere. Exist ă
mai multe niveluri la care poate fi abordat ă traducerea. Cel mai general ea este o
funcție , unde este alfabetul de intrare iar
* *:Δ → Σ f Σ Δ este alfabetul de ie șire.
Deci, traducerea este o submulț ime dacă ; T* *Δ × Σ ⊂()T y , x∈, atunci este
traducerea lui y
x.
II.1.2.1 Scheme de traducere orientate de sintax ă
Definiția 1.1. O schemă de traducere orientat ă de sintax ă (STOS) este un
5-tuplu , unde : () S R, , , N, = SΔ Σ
– N este mul țimea neterminalelor,
– Σ este alfabetul de intrare ,
– Δ este alfabetul de ie șire,
– R este o mul țime de reguli de forma βα, A→ unde ()(* *, Δ ∪ ∈ Σ ∪ ∈N N β α
Automate, limbaje și compilatoare
85 )
iar neterminalele din β sunt (eventual) o permutare a celor din α,
– S este un neterminal având rolul de simbol ini țial.
Toate mulț imile de mai sus se presupun a fi finite. Fie βα, A→ o regulă;
fiecare neterminal din α este asociat cu unul identic din β. Dacă un neterminal
Definiția
schemei de
traducere
Automate, limbaje și compilatoare
86 B apare de mai multe ori în α și β vom folosi indici supe riori pentru a pune în
evidență asocierea. De exemplu, în regula este
asociat cu ) ( ) ( ) ( ) ( ) (B , C B B , CB B A1 1 2 2 1→
) (B1, . C cu C B cu B ) ( ) (2 2 si
Definiția 1.2. Numim form ă de traducere în STOS ( )S R, , , N, SΔΣ= o
pereche ( obținută conform regulilor: *)*N )Δ × Σ ∪ ∈ ( (
AN∪ v u) ,
)S (1) este o form ă de traducere, în care cele dou ă neterminale sunt
asociate; , S( S
(2) dacă ) A , (1 1 βαβα este o form ă de traducere în care cele dou ă
simboluri A sunt asociate și R), A ( ∈→1 γγ , atunci ) , (1 1 1 βγααγβ este o form ă
de traducere. Neterminalele din 1γ și γ sunt asociate exact ca în regul ă, iar cele
din șiαβ sunt asociate cu cele din 1αși 1β
)1 1 1 exact ca în vechea form ă de
traducere.
Pentru a defini rela ția dintre cele dou ă forme de traducere vom scrie:
, ( , A ( )1A1 βγααγββαβα
S⇒ .
Vom utiliza nota țiile: , și pentru închiderea tranzitiv ă, închiderea
reflexivă și tranzitiv ă și respectiv derivarea în k pa și. Dacă nu exist ă pericol de
confuzie, nu vom mai specifica schema de traducere S . Traducerea definit ă de
STOS S este +
⇒
Sk
S⇒*
S⇒
τ(S) .
⎭⎬⎫Δ ∈ Σ ∈* *y si x , ) y ,
) P , , N ( Gi iΣ⎩⎨⎧= ) /( , x (
R, SΣ⇒*
x ( S , S
( , ,Δ) y
N,= Definiția 1.3. Fie o STOS. Gramatica S )S , =
unde {} R ,α
) P ,Δ)∈β
S ,eA ( Pi → =α
, N ( Ge=A (→ se nume ște gramatica de intrare a schemei
S.. Gramatica unde { }R ) , A ( A ( Pe ∈→ → =β α β se numește
gramatica de ie șire a schemei S .
Schema de traducere orientat ă de sintax ă poate fi privit ă ca o metod ă de
transformare a arborilor de derivare din gramatica în arbori de derivare din
gramatica . iG
eG
Algoritmul 1.1. – de transformare a arborilor
Traducerea
realizată de
schema
Automate, limbaje și compilatoare
87 Intrare: o STOS ( )S R, , , N, SΔ Σ = cu gramatica de intrare ) S , P , , N ( Gi iΣ= ,
gramatica de ie șire ) S , P , , N ( Ge eΔ= și arborele de derivare în cu frontiera
. DiG
*xΣ ∈
Ieșire: un arbore de derivare 'D în cu frontiera astfel încât
. eG*yΔ ∈
) ( ) y , x (Sτ ∈
Metoda :
(P1) Aplică pasul (P2), recursiv , începând cu nodul r ădăcină al lui D.
(P2) Fie nodul că ruia i se aplic ă acest pas. Presupunem c ă este nod interior
și are ca descenden ți nodurile : q q
kq ,…., q1
(a) Șterge descenden ții direcți ai lui care sunt noduri maximale (etichetate cu q
ε sau cu terminale).
(b) Fie producția din reprezentat ă de nodul și descenden ții săi; α → AiG q A
este eticheta lui iar α este o secven ță formată prin concatenarea etichetelor
nodurilor . Fie q
kq,…., q1 R ) A (∈ →,βα ; permută neterminalele din α în ordinea
dată de β, subarborii domina ți de aceste noduri r ămânând neschimbaț i.
(c) Inserează noduri maximale cu etichete din β în ordinea dat ă de β.
(d) Aplic ă pasul (P2) descenden ților direc ți ai lui q care sunt noduri
nemaximale, în ordinea de la stânga la dreapta.
(P3) Subarborele rezultat este . Δ'
Definiția 1.4. O STOS ( )S R N, , , , SΔΣ= astfel încât în fiecare regul ă
neterminalele asociate apar în aceea și ordine în α și β se nume ște
schemă simplă de traducere orientat ă de sintaxă (SSTOS). β α →, A
II.1.2.2. Traduc ătoare finite
Traduc ătoarele finite sunt automate finite înzestrate cu ie șiri. Un
traducător finit, pornind dintr-o stare dat ă trece în altă stare și emite o secven ță pe
un alfabet de ie șire când prime ște un simbol de intrare sau simbolul vid (notat
ε ).
Definiția 1.5 . Un traduc ător finit F este un 6-tuplu ( )F , q , , , , Q0δΔΣ unde
– Q este mul țimea stărilor,
Relatia dintre
scheme și
gramatici
– Σ este alfabetul de intrare,
– Δ este alfabetul de ie șire,
– δ este func ția de transfer; {}()*
fQ ) ( Q :Δ × → ε ∪ Σ × δ P unde P înseamnă f
mulț imea părților finite,
– este starea ini țială, Q q∈0
– este mulțimea stărilor finale. Q F⊆
Toate mul țimile de mai sus sunt finite.
Definiția 1.6. Numim configura ție a traduc ătorului finit F un triplet
unde : ( y , x , q)
– este starea curent ă, q
– x este porțiunea din secven ța de intrare r ămasă de citit,
– y este secven ța emisă pe banda de ie șire până în momentul curent.
Definim
, relație binară între configura țiile lui F . Pentru
și astfel încât {}*x , a , Q qΣ ∈ ∪ Σ ∈ ∈ε*yΔ ∈ ()a , q ) z , r (δ∈ cu Q r∈ și
scriem () *zΔ ∈
y , ax , q
() . yz , x , r
Notăm cu
,
,
închiderea tranzitiv ă, închiderea reflexiv ă și
tranzitivă și respectiv trecerea în i pa și. Dacă pentru {}()*xε ∪ Σ ∈ există
și astfel încât *yΔ ∈
F q∈ ()ε, x , q0
( y , , q)ε spunem c ă y este traducerea lui x și
notăm Traducerea definită de F notat ă ). x (τ =y
τ(F) este () ({ )ε, x , q / y , x0
() F q y , , q
Automate, limbaje și compilatoare
88 }∈ pentruε .
Definiția 1.7. Traducătorul finit F este determinist dac ă pentru orice
: *Q q∈
(1) sau con ține cel mult un element pentru orice )a , q (δ a∈Σ și δε(,)q este
mulțimea vidă sau
(2) conține un element ș i pentru orice ), q (ε δ ()a , q , aδΣ∈ este mulțimea vidă.
II.1.2.3. Traduc ătoare pushdown
O alt ă clasă important ă de traduc ătoare o reprezintă traduc ătoarele
pushdown. Un astfel de traduc ător este un automat pushdown înzestrat cu o
Definiția
traducătorului
finit
Funcționarea
traducătorului
finit
ieșire.
Definiția 1.8. Se nume ște traduc ător pushdown un 8-tuplu
, unde toate simbolurile au aceea și semnifica ție ca în
cazul automatului finit, exceptând pe P ) F , Z , q , , , , , Q (0 0δ Δ Γ Σ =
Γ care este alfabetul (memoria) pushdown
iar . {}) ( Q :→ Γ × ε ∪ Σ × δ ) Q (* *
fΓ × P Δ ×
Definiția 1.9. Se numește configura ție a lui P un 4-tuplu ()y , , x , qα
unde
– este starea curent ă, q
– x este por țiunea din secven ța de intrare r ămasă de citit,
– α este conținutul memoriei pushdown,
– y este secven ța emisă pe banda de ie șire până în momentul curent.
Dac ă (Z , a , q ) z , , r ()δα∈ scriem ) y , Z , ax , q (γ
) yz , , x , r (αγ pentru
. Spunem că *yΔ ∈ * *și , xΓ ∈ γ Σ ∈ y este traducerea lui x și scriem ,
dacă ) x (τ =y
)ε, Z , x , q (0 0
) y , , , q (α ε pentru . Traducerea definit ă de
notată este *și FΓ ∈ α q∈
P ) (Pτ() ( ) { ε, Z , x , q y , x0 0
() }*FΓ ∈ ∈α și q y , , ,α ε pentru q .
y este traducerea lui x cu memorie pushdown vid ă dacă
()ε, Z , x ,0 q0
) y , , , q (ε ε pentru un Q q∈. Traducerea definit ă de P cu memoria
pushdown vidă, notat ă ) (Pετ este ()() {
Automate, limbaje și compilatoare
89 ε, Z , x , q y0 0 , x
() Q y , , , q ∈} q un pentru εε .
Definiția 1.10. Traducă torul pushdown P ) F , Z , q , , , , , Q (0 0δΔΓΣ=
este determinist dacă :
(1) pentru orice {} ) Z , a , q ( , z a , Q q δΓ∈ε ∪ Σ ∈ ∈ și conține cel mult un element
și
(2) dacă , atunci ∅ ≠ ε δ) Z , , q ( ∅=δ ) Z , a , q ( pentru orice a∈+Σ.
La fel ca în cazul automatelor pushdown, are loc echivalen ța din
Teorema 1.1. Traducerea τ este realizat ă de traduc ătorul pushdown P
dacă și numai dac ă ea este realizat ă de un traduc ător pushdown P cu memoria 1
2
Definiția
traducătorului
pushdown
Funcționarea
traducătorului
pushdown
pushdown vidă .
Teoremele urm ătoare arată că traducătoarele pushdown caracterizeaz ă
clasa schemelor simple de tr aducere orientate de sintax ă în aceea și manieră în
care automatele pushdowm caracterizeză limbajele independente de context.
Teorema 1.2. Pentru orice SSTOS exist ă un traduc ător pushdown P
astfel încât τ(S)=τε( P )
Demonstra ție. Fie S= o SSTOS. Vom avea nevoie s ă facem
distincție între simbolurile lui Σ și cele ale lui Δ. De aceea vom înlocui Δ cu un
alfabet ) S , R , , , N (Δ Σ
'Δ astfel încât ∅ = Δ ∩Σ ' . 'Δ conține un nou simbol pentru fiecare
Fie homomorfismul definit prin ' a
. aΔ ∈ h ' a ) a ( h= pentru Σ∩Δ∈a și P
{}() ∅ δ ΔΔ, '∪ Σ N∪Σ, , S , q , , ' , q = unde funcț ia δ este definit ă astfel:
(1) dacă () R y B … y B y , x B … x B x Ak k k k ∈ →1 1 0 1 1 0
() A , , qε cu
atunci conține pe ()N B , ' y , x , ki*
i*
i ∈ Δ ∈ Σ ∈ ≥ 0
δ ε), y ( h x Bk k k )…1y ( h x B ) y ( h1 1 0 0x q,
(2) pentru orice () ({ε ε = δ, , q a , a , q)} Σ∈a
(3) pentru orice () ({ a , , q ' a , , qε = ε δ)} Δ∈a .
Se arată, prin inducț ie după și , că m n
“pentru orice și pentru un anumit N A∈ () ) y , x ( A , A n , mm
⇒ ≥ 1 m
dacă și numai dac ă () ε, A , x , q
()y , , , qεε pentru un anumit ”. n
Luând avem dacă și numai dac ă S A=() ) y , x ( S , S*
⇒ ()ε, S , x , q
()y , , , qε ε,
deci . ()Pτ =()Sτε
Teorema 1.3. Fie P ( F , Z ,0 =0q , , , , Q,) δΔΓΣ un traduc ător pushdown .
Atunci exist ă o SSTOS S astfel încât ()()P Sετ=τ .
Demonstra ție. Construc ția este similară cu cea a ob ținerii unei gramatici
independente de context di ntr-un automat pushdown. Fie S ()S R N, , , ,ΔΣ = unde
(1) []{} S A , Q q , p / pAq N∪ Γ ∈{} ∈ =
(2) R este definită astfel
(a) dac ă atunci, pentru conține regulile () ( A , a , p y , x … x x , rkδ ∈2 1
Automate, limbaje și compilatoare
90 ) R , k0>
[][] [ ] [ ] [][][]k k k k k k q x q … q x q q rx y , q x q … q x q q rx a pAq1 2 2 1 1 1 1 2 2 1 1 1 − − →
Q q …, , q , qk∈2 1 qk= 0=k pentru orice
și q . Pentru regula este [] , a pAr→ y
Teoremele 1.2
și 1.3
echivaleaz ă
schemele de
traducere cu
traducatoare pushdown
(b) pentru orice R , Q q∈ conține regula [][]q Z q , q Z q S0 0 0 0 →
Prin induc ție după m și n se arată că dacă și numai
dacă [] []() ) y , x ( pAq , pAqm
⇒
()ε, A , x , p
( y , , , qε)ε pentru orice Q q , p∈ și Γ∈A . Apoi avem
dacă și numai dac ă ()() y , q , S , S0[] q Z q⇒0 0[] x q Z+
⇒0
Automate, limbaje și compilatoare
91 ( ) ()ε, Z , x , q0 0
()y , , , qεε deci
. ()S= τP)(ετ
Teorema 1.4. Dacă S este o SSTOS atunci ()Sτ∈t dacă și numai
dacă există un traduc ător pushdown P astfel încât ()Pτ∈t .
Demonstra ție. Rezultă din teoremele 1.17, 1.18 și 1.19.
II.2. ANALIZA LEXICAL Ă
II. 2.1. Generalit ăți
Analiza lexicală este prima faz ă a compilă rii, rolul s ău fiind de a citi
caracterele de intrare și a produce la ie șire o secven ță de atomi lexicali (tokens ,
în engleză ) utilizați apoi în analiza sintactic ă.
Un atom lexical este un reprezentant al unei clase de șiruri de caractere
cu reguli precise de formare. În majoritatea limbajelor de programare,
următoarele construc ții sunt tratate ca atomi lexica li: identificatori, constante,
cuvinte cheie, operatori, ș iruri de caractere, semne de punctua ție ( paranteze,
virgulă, punct și virgulă, etc. ), etc. Sarcina analizei lexicale este s ă selecteze în
șirul de caractere al programului surs ă subș iruri ce respect ă regulile de formare a
atomilor lexicali, s ă clasifice aceste sub șiruri ș i să le traducă în atomi lexicali.
Un atom lexical va fi reprezentat printr-o pereche < clasa atomului,
valoarea sa >. Pentru atomii care au o valoare particular ă nu vom mai folosi
perechea, ci vom pune în eviden ță numai valoarea. De exemplu, pentru
instrucțiunea
COST = (PREȚ+TAXA) × 0.45
se pun în eviden ța următorii atomi lexicali
<id, COST> ; = ; ( ; < id, PRE Ț > ; + ; < id , TAXA > ; ) ; × ; 0.45
Analiza lexicală trebuie să furnizeze informa ții mai detaliate care servesc
și în alte scopuri; acestea sunt colectate în atributele asociate . În general exist ă un
Automate, limbaje și compilatoare
92 )singur atribut – un pointer spre ta bela de simboluri unde se afl ă depusă valoarea
atomului. Analiza lexical ă poate fi implementată ca o fază separată sau se poate
întrepătrunde cu analiza sintactic ă. Separarea celor dou ă faze are urm ătoarele
avantaje :
– proiectarea este mai simpl ă, conform principiului modularit ății ;
– sintaxa atomilor lexicali poate fi exprimat ă printr-o gramatic ă regulată; deci
analiza lexicală poate fi efectuat ă de un automat finit și nu de unul pushdown, ca
în cazul analizei sintactice ;
– analiza lexical ă curăță textul de informa țiile inutile: comentarii, blancuri.
Analizorul lexical poate fi comandat de cel sintactic; în acest caz el apare ca o rutină a analizorului sintactic pe care acesta o apeleaz ă ori de câte ori are
nevoie de un nou simbol.
II. 2.2. Proiectarea unui analizor lexical
În cazul unui analizor lexical complex, acesta va fi descompus în „buc ăți“
ce vor fi legate între ele în vederea ob ținerii rezultatului final. Exemplific ăm cele
spuse mai sus folosind urm ătoarea gramatic ă:
(G0 (1) <șir atomi>:=<atom>/< șir atomi><atom>
(2) <atom>:=<id>/<const>/<op>/<del>/<com> (3) <id> :=<lit>/<id><lit>/<id><cif>
(4) <const>:=<c if>/<const><cif>
(5) <op>:=+/*/</<=/>/>=/=/<> (6) <del>:=;/blanc
(7) <com>:=*/<orice șir ce nu con ține grupul */>*/
(8) <lit>:=A/B/C/…./Z/a/…../z
(9) <cif>:=0/1/…/9
Gramatica
) nu este regulat ă, dar poate fi transformat ă în una regulat ă
rescriind produc țiile. De exemplu, produc ția (4) se poate scrie G (0
<const>=0/1/2/…/9/<const>0/<const>1/…/<const>9.
Pentru a u șura proiectarea analizorului lexical, se prefer ă stratificarea gramaticii
într-o ierarhie de gramatici mai simp le, regulate, care apoi trebuie cuplate
astfel încât limbajul generat s ă rămână același. Stratificarea începe cu
partiționarea mulț imii neterminalelor și stabilirea unei ierarhii între elementele
partiției. În cazul nostru putem realiza urm ătoarea parti ție: ) G (0
Structura
atomilor lexicali
Automate, limbaje și compilatoare
93 {}
{}
{} > < > < => < > < > < > < > < => < > < =
cif , lit Ncom , del , op , const , id Natom , atomi sir N
321
Cu ajutorul acestei parti ții, descompunem gramatica în trei gramatici;
pentru fiecare gramatic ă vom considera ca terminale, pe lâng ă terminalele din
, și neterminalele din grupul imediat inferior în ierarhie. Cele trei gramatici
vor fi : )(0G
) G (0
p/del/com id/const/o: atomatom atomi sir / atom : atomi sir : ) (G1
= > <> >< < > =< > <
<> = >= > <= < ∗ + = > <> < = > <> < > < >= <
/ / / / / / / : op : ) (Gcif const cif/ : const : ) (Gcif id lit/ id lit/ id : ) (G
232221
*/ / * grupul contine nu ce caractere de sir orice */ : com : ) (G/blanc ; : del : ) (G
2524
> < = > <= > <
0/1/…/9 : cif : ) (Ga/…/z A/B/…/Z/ : lit : ) (G
3231
= > <= > <
Noile gramatici sunt regulate, cu excep ția lui și . Le putem, însă ,
transforma, la fel cum am transformat anterior produc ția (4). Fiecare gramatic ă va
fi modelat ă printr-un automat finit; fiecare automat de pe un nivel inferior trebuie
să transmită nivelului superior informa ția de acceptare a șirului inspectat. 1G25G
Cuplarea automatelor și se face în serie, ie șirea unuia fiind
intrare pentru cel ălalt. Automatele ce se cupleaz ă trebuie să satisfacă următoarele
condiții: 2 1A , A3A
– s ă fie deterministe;
– orice simbol primit la intrarea unui automat și care nu activeaz ă nici o
tranziție trebuie s ă conducă la o situa ție de eroare.
În cazul nostru nedeterminismul apare în cazul automatului A2 și se manifest ă
prin existen ța a două tranziții din starea ini țială pentru simbolul ∗. În diagrama
ce o vom prezenta mai târziu vom înl ătura acest nedeterminism. Diagramele de
tranziții ale automatelor se vor completa cu proceduri semantice, care au ca scop
restabilirea la sfâr șitul analizei unui atom lexi cal a unui context adecvat c ăutării
următorului atom, emiterea unei ie șiri corecte care s ă reprezinte atomul analizat și
semnalarea erorilor.
Proiectarea
unui analizor
lexical prin stratificarea gramaticii
Automate, limbaje și compilatoare
94 În figura urmatoare este prezentat ă diagrama de tranzi ții a automatului
completată cu procedurile semantice CITCAR și IESCAR . 3A
Procedura CITCAR este apelat ă înainte de începutul func ționării automatului și
are rolul de a prelua din fi șierul de intrare caracterul urm ător. Procedura IESCAR
furnizează ieșirea automatului ; ea este format ă din clasa caracterului și
caracterul propriu-zis. În figura urmatoarese prezint ă diagrama de tranzi ții a
automatului completat ă cu procedurile AD, CARNOU și IEȘIRE. A3
A2
Automate, limbaje și compilatoare
95
Procedura AD este folosit ă pentru construc ția identificatorilor și
constantelor. Ea adaug ă într-un tablou de caractere ( șir) caracterul primit la
intrare. Tabloul acumuleaz ă toate caracterele identifi catorului sau constantei
analizate. CARNOU simulează intrarea automatului aducând urm ătorul caracter
din textul surs ă, dar clasificându-l conform automatului . Procedura IEȘIRE
formează ieșirea automatului , alcătuită din clasa automatului ș i atomul
lexical. 3A
2A
În mod similar se proiecteaza diagrama de tranzi ție a automatului
completată cu procedurile semantice CAUTĂID, CAUT ĂNR, SELECT . 1A
La fel ca în majoritatea limbajel or de programare, comentariile și blancurile sunt
eliminate. Procedura CAUTĂID caută în tabela de simboluri identificatorul din
tabloul șir și dacă nu-l găsește îl introduce. Ea înto arce adresa la care se g ăsește
identificatorul, completând cu ea a doua informa ție din atomul lexical. Dacă
identificatorul este cuvânt cheie, se înlocuie ște clasa atomului cu numele
cuvântului cheie iar a doua component ă se omite. Procedura CAUTĂNR
determină valoarea constantei numerice din tabloul șir și caută în tabela de
simboluri dac ă există o constant ă cu aceeași valoare. Dac ă nu o gă sește, valoarea
din șir este plasată în tabelă. Procedura determin ă adresa intr ării corespunză toare
constantei și memoreaz ă adresa în atomul lexical. Procedura SELECT discerne
blancul de ; .
Teme Curs
Teste Autoevaluare
1. Care este deosebirea dintre analiza sintactic ă și cea semantic ă?
……………………………………………………………….…………….. 1 punct
2. Fie STOS S {}{ }{ }( )E , R , a , , , a , , , E× + × + = unde R este mulțimea de reguli:
a , a EE E , E E EE E , E E E
) ( ) ( ) ( ) () ( ) ( ) ( ) (
→× × →+ + →
2 1 2 12 1 2 1
Să se găsească traducerea secven ței a a a×+ …………………. 2.5 puncte
3. Consider ăm STOS S {}{}{} ( , A S , , , , , 1 0 = )S R b , a unde R este format ă din
regulile
b , Ab , SASa , SA ASAa , AS S
1100
→→→→
Folosind algoritmul de transformare a arborilor, s ă se găsească traducerea
secvenței 00111 ………………………………………………………………….2.5 puncte
4. Fie traducă torul pushdown P{}{}{}{}{} ( )q , E , q , , , , a , E , , , , , a , qδ×+×+×+ = und
funcția de transfer este definită astfel: e
()(){}
() ({}ε + = + δ
Automate, limbaje și compilatoare
96 )ε=δ
, EE , q E , , qa , , q E , a , q
()(){}
() (){}
() (){}× ε = × ε δ+ ε = + ε δε×=× δ
, , q , , q, , q , , q, EE , q E , , q
Care este traducerea secven ței aaa×+ ?………. ………………..2.5 puncte
5. Este mai avantajos ca analiza lexical ă să fie separat ă de cea sintactic ă?
………..……………………………………………………………………0.5 puncte
Oficiu……………………………………………………………………… 1 punct
Automate, limbaje și compilatoare
97 Răspunsuri
1. Analiza semantic ă extinde arborele construit în analiza sintactic ă
2. Avem derivarea:
), aaa , a a a () aaE , E a a () E aE , E E a () E E E , E E E () E E , E E ( ) E , E (
) ( ) () ( ) ( ) ( ) () ( ) ( ) ( ) ( ) ( ) () ( ) ( ) ( ) (
+ × × + ⇒+ × × + ⇒+ × × + ⇒+ × × + ⇒+ + ⇒
4 44 3 4 34 3 1 4 3 12 1 2 1
deci + × = × + τ aaa ) a a a (
3. bbbaa ) (= τ 00111
4. Traducerea secven ței aaa× + se desfășoară astfel
() ε × +, E , aaa , q
() ε+× , EE , aaa , q
() ε+× , E EE , aaa , q
() a , E E , aa , q+×
() aa , E , a , q+ ×
() ×+aa , E , a , q
() a aa , , , q× + ε
() +× ε εa aa , , , q.
Deci, traducerea , cu memoria pushdown vid ă , a secven ței aaa×+ este
+ ×a aa
5. DA
Rezumat: S-au prezentat etapele ce trebui e parcurse în vederea proiect ării
unui compilator, apoi metode de tradu cere a limbajelor. În partea a doua s-
a explicat modul de efectuare a analizei lexicale.
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Automate, limbaje și compilatoare
98
Realizarea unor anal izoare lexicale, ca prim ă etapă a construirii unui compilator
Teme Laborator/Seminar
1. Proiectați un analizor lexical care s ă recunoască constantele aritmetice
și alfanumerice cuprinse între ghilimele.
2. Proiectați un analizor lexical care s ă recunoască identificatorii și
cuvintele cheie
Rezumat: Se proiecteaz ă analizoare lexicale care s ă recunoasc ă elementele
de bază ale unui limbaj de programare.
Automate, limbaje și compilatoare
99 Notații
Automate, limbaje și compilatoare
100
Curs 7 Analiza sintactic ă (I)
Descriere Generală
Se prezint ă pricipiile de func ționare ale analizei lexi cale de tip ascendent ș i
descendent, apoi se dau algoritmi generali de analiz ă sintactică
Obiective
– însușirea principiilor de func ționare ale anal izei sintactice
– cunoaș terea principalilor algoritmi de analiz ă sintactică, ce funcț ionează pe
baza backtrackingului
Cuprins
II.3.1. Formularea problemei
II.3.2. Algoritmi generali de analiz ă sintactică
II.3.2.1. Analiz ă sintactică descendent ă
II.3.2.2. Analiza sintactic ă ascendent ă
II.3.2.3. Algoritmul Cocke -Younger – Kasami (CYK)
Conținut Curs
II.3.1. Formularea problemei
Fie ( S , P , , N G)Σ= o gramatic ă independent ă de context (GIC) ș i
; spunem c ă a fost efectuat ă analiza sintactic ă a secven ței ) G ( L∈ α α dacă a
fost găsit cel pu țin un arbore generator pentru α . Se lucreaz ă cu analiz ă
sintactică la stânga sau la dreapta. Presupunem c ă gramatica G are produc țiile
numerotate de la 1 la și . Scriem pα(*N ,Σ ∪ ∈β) α
β dacă se foloseș te
producția cu num ărul i iar neterminalul care deriveaz ă este cel mai din stânga.
Similar scriem α
β dacă se foloseș te producț i a c u n u m ărul iar
neterminalul care deriveaz ă este cel mai din dreapta. Aceste nota ții se extind
astfel : i
(1) dacă α
β și β
γ atunci α
γ
(2) dacă α
β și β
γ atunci α
γ . Dacă ni … i i2 1=π , notăm Curs 7
Durata :
2 ore
Definirea
analizei sintactice
Automate, limbaje și compilatoare 101
~….π=−ii inn 1
,1∈ π1. Dacă , se nume ște analiză sintactică la stânga o
secvență astfel încât ) G ( L∈ α
}{*p …, , 2 S
α. Se numeș te analiză sintactică la
dreapta a cuvântului , o secven ță α {}p*,…, ,2 1~π∈ astfel încât S
α .
Exemplul 3.1 Fie {}{}{ },6 () E , , , , ) , ( , 5 4 2 1, ,3 * a ,, , F ,T , E G + =
→
F→
F
1. 4. T T E+
F * TE→
T E→
T→
a a+ = αF
(
a→ 2. 5. ) E
3. 6.
și . Avem
E
E+T
T+T
F+T
a+T
a+F
a+a
deci analiza sintactic ă la stânga este 124646=π .
La fel E
E+T
E+F
E+a
T+a
F+a
a+a
deci analiza sintactic ă la dreapta este 642641=π~.
Dispozitivele care furnizeaz ă analiza sintactic ă la stânga se numesc
descendente (top – down), datorit ă modului în care construiesc arborele de
derivare – de la ră dăcină spre nodurile maximale. Ana lizorii sintactici la dreapta
se numesc ascenden ți (bottom-up), arborele fiind c onstruit începând cu nodurile
maximale și efectuând reduceri pân ă se obține nodul ră dăcină.
II.3.2. Algoritmi generali de analiz ă sintactic ă
Se pot construi scheme de traducere orientate de sintax ă sau traduc ătoare
pushdown pentru a efectu a analiza sintactic ă. Aceste dispozitive func ționează,
însă, nedeterminist, ceea ce impune utilizar ea backtracking-ului pentru a putea
continua analiza în caz de blocaj. De aceea vom prezenta algoritmi care au
backtracking-ul implementat sau vom utiliza gramatici care permit efectuarea
analizei sintactice în mod determinist.
II.3.2.1. Analiz ă sintactică descendent ă
Operaț iile ce trebuie efectuate de un analizor sintactic bazat pe modelul
traducătorului pushdown nedeterminist su nt: înlocuirea unu i neterminal A din
vârful stivei cu un șir ce reprezint ă o parte dreapt ă a A -producț iilor
gramaticii și ștergerea unui terminal din vârful stivei în cazul în care el coincide
Automate, limbaje și compilatoare 102
cu terminalul curent de la intrare, urmat ă de avansul cu o pozi ție la dreapta pe
banda de intrare. Deci, un astfel de an alizor sintactic va propune pentru fiecare
neterminal alternative de rescriere a lui, opera ție numită expandare. Fiecare
alternativ ă va reprezenta o structur ă posibilă pentru urm ătoarele simboluri de
nta principi ul analizei sintactice cu reveniri s ă
nsiderăm urm rea gramatic ă intrare.
Dac ă structura nu este reg ăsită în șirul de intrare, an alizorul trebuie s ă
propună o altă alternativ ă. Modelul de analizor pr ezentat anterior nu încearc ă
următoarea alternativ ă de expandare; vom prezenta mai târziu un analizor care are
această proprietate. Pentru a preze
co ătoa
() S , P , , N GΣ = , P{} ddc / ccd B , c / b A , aB / aAd S→→ →= și fie
entruaccd
cuvântul de analizat . Se porne ște cu simbolul ini țial ca nod r ădăcină , se alege prima alternativ ă
pentru
S și prima alternativ ă pentru A. Deoarece secven ța generat ă nu se
regăsește în șirul de intrare se alege urm ătoarea alternativ ă pentru A. Nici de data
aceasta, secven ța generată nu se reg ăsește în cea de intrare; deoarece nu mai sunt
alternat e p iv A, se alege urm ă ativă pentru i apoi prima
entrutoarea altern S ș
p B .
wn și
) și un indicator pe banda de intrare, ce precizeaz ă poziția curentă.
lgoritmul 3.1
rare: o G I C , f
Algoritmul pe care-l prezent ăm utilizeaz ă două benzi pushdo (1B
2B
A
Int ără recursie stâng ă ()S , P , , N GΣ= și un cuvânt de
intrare . Presupunem c ă umerotate cu
ntactică la stânga a lui w, dacă aceasta exist ă; în caz contrar se
i02 1≥ = n , a … a a wn producțiile sunt n
p …, , ,2 1 .
Ieșire : analiza si
afișază ,, eroare“.
Metoda. Pentru fiecare neterm nal A, dacă k/ … A /ααα2 s u n t t o a t e 1→ A-
producțiile, se noteaiA alt ză cu nativaer i Aα→ . Algoritm ul utilizea ză
configuraț ii de forma ()βα, , i , s unde
(a) s este starea algoritmului și poate lua una din valorile
king ) – în cazul func ționării normale q•
– în cazul relu ării derivației (backtrac b•
Principiul
analizei
descendente
Automate, limbaje și compilatoare 103
• onfigurației de terminare
( b ) {} 1 2 1t – în cazul c
+ ∈ n …, , , i este pozi ția curentă pe banda de intrare; al – lea
de intrare este a.
ta, ce înregistreaz ă alternativele încercate ș i simbolurile de intrare
ate. 1+n
simbol $, folosit pe post de delimitator la dreapt
(c) {}()*
iA∪ Σ ∈α reprezint ă conținutul benzii pushdown 1B, bandă cu vârful
spre dreap
verific
(d) (∪ Σ ∪ ∈ Nβ{$})* reprezint ă conținutul benzii pushdown 2B, bandă
cu vârful spre stânga. Simbolul din vârf reprezint ă nodul activ al arborelui de
amaticii.
gurație la alta se face conform urm ătorilor paș i: derivare.
Configura ția inițială este () $ S , , , qε1 , unde S este simbolul ini țial al gr
Trecerea de la o confi
Pasul 1 . expandare
)βA (α, , i , q
() βγ α1 1, A , i , q
unde () P A∈ γ →1 și 1γ este prima alternativ ă pentru A. Acest pas corespunde
extinderii arborelui par țial de derivare uti lizând prima alternativ ă pentru
neterminalul cel mai din stânga din arbore.
Pasul 2 . Concordanță între simbolul de intrare și cel derivat
(αa , , i , q)β
() βα +a , i , q1 ,
Se efectueaz ă când n i , a ai ≤ ≤ = 1 constă în mutarea simbolului terminal
din vârfși
ul benzii și mutarea indicatorului pe banda de B2 în vârful benzii 1B
intrare.
Pasul 3 . Obținerea unei configura ții de acceptare
() $ , , n , qα +1
() εα +, , n , t1
Ajungerea în această configura ție spune c ă a fost epuizat ă banda de intrare și a
fost găsit un arbore de derivare stâng plicând homomorfismul
aă. Acesta este g ăsit a
h lui α : pentru orice ε =) ( h Σ∈a și j ) A ( hi= dacă j este produc ția
()iA A=γ→ .
Pasul 4 . Sim re bolul de intra nu co incide cu cel derivat
()β αa , , i , q
()β αa , , i , b dacă a ai≠
Pasul 5 . înto zi arcerea pe banda de intrare cu o po ție
()β α, a , i , b
() Σ∈∀ − a a , , i , bβα1 Algoritm de
analiză
descendent ă
bazat pe backtracking
Automate, limbaje și compilatoare 104
Pasul 6 . în
cercarea alternativei urm ătoare
( )βγαj A , i , bj,
( )βγα+ +1 1j j, A , i , q d a că 1+γj este a – a 1+j
alternativ ă pentru A
fără continuare dac ă S A , i==1 și exista numai j
alternative pentru A; nu e e derivare pent ru cuvântul de intrare
xistă arbore d
()βαA , , i , b în caz contrar ; au fost epuizate toate
lternativele pentru a A ș la expandarea acestui nod .
lgoritmul se execut ă astfel: i se renun ță
A
Pasul 1 : Se o e ș p rn te cu configuraț ia inițială și se calculeaz ă configura țiile
succesive 0C
1C
…
rC
Pasul 2 : Dac ima configura ție este ă ult ()εγ+ , , n , t1 se emite ) ( hγ lgoritmul
se oprește , ) ( hși a
γ fiind primul arbor e de derivare g ăsit. e s t e o
configuraț ie fără continuare, se emite semnalul „ eroare “ .
II.3.2.2. Analiza sintactic ă ascendent ă
este pus în evidenDacă γC
Principiul de funcț ionare a unui analizor sintac tic ascendent cu reveniri
ță ând gram în figura 3.2, utiliz atica cu regulile
aba B , ab A , AB S→ → → și cuvântul de intrare wababa=
Se foloseș te pentru reducere prima regul ă posibilă, ab A→ . Deoarece nu exist ă
nici-o regul ă de produc ție care să aibă în mem pt secven ța AAa
renunță la ultima reducere brul dre
aba→, se
și se folose ște regula ; în final sec B vența AB
se reduce la
goritmul 3.2
Intrare: fo S.
Al
() S , P , , N GΣ = o GIC, f ără cicluri (nu con ține produc ții de rma
A
A ) ii, , fără – producț cu producț iile numerotate de la la ε 1 p și cuvântul
borele de derivare la dreapta, dac ă există, și ,, eroare “ în caz contrar .
cție; de intrare 12 1≥ = n , a … a a wn .
Ieșire : ar
Metoda :
• se ordoneaz ă arbitrar regulile de produ
• se lucreaz ă cu configura ții de forma ()βα, , i , s unde
Principiul de
funcționare a
analizei ascendente
Automate, limbaje și compilatoare 105
a) s reprezint ă starea algoritmului și poate lua una din valorile
mală,
ică simbolul curent de pe banda de intrare; pe pozi ția – : pentru func ționare nor q
– b : pentru mersul înapoi,
– t : pentru încheierea cu succes a analizei;
b) i ind 1+n se află
ul $
rful spre
ta ) și reprezint
dă ține eviden ța reducerilor efectuate pentru a se ob ține
configuraț ia iniț ială este simbol
c ) {}()*$ N∪ Σ ∪ ∈ α este con ținutul benzii pushdown 1B ( cu vâ
dreap ă porțiunea în care a fost redus ă secvența de intrare
d) {}*s , p …, , , 2 1∈ β reprezint ă conținutul benzii pushdown 2B ( cu vârful spre
stânga ); acea stăban
conținutul lui 1B.
• ()ε$, , , q1 .
Pasul 1 : încercare de reducere
)γ αβ, (, i , q
()γ αj , A , i , q
unde β → A este produc ția cu num ărul j. Dacă s-a efectuat pasul 1 se r ămâne la
ontrar se merge la pasul 2 . acest pas ; în caz c
Pasul 2 : trecere
()i , qγ α, ,
() γα + s , a , i , qi 1
cu con 1+n ; apoi se merge la pasul 1.
Dacă 1+ =n i se merge la pasul 3 . Simbolul diția ≠i
s de pe banda pushdown 2B arată
unui simbol de pe banda de intrare pe banda
asul 3că a avut loc o trecere a 1B.
P : acceptare
() γ +, S $ , n , q 1
()+, n , t1
ul se și se em e γ, S $
Algoritm opre ște ite und este homomorfismul definit prin
e la pasul 4. ) ( hγ, h
ε =) s ( h și j ) j ( h= pentru {} p …, , , j 2 1∈ .
Dacă pasul 3 nu s-a executat se merg
Pasul 4 :
; următoarea produc ție, în ordinea
Algoritm de
analiză
ascendent ă
bazat pe
backtracking
începutul mersului înapoi
()γα, ,1+n , q
( )γ α +, , n , b1
cu condiția S $≠α . Se m erge la pasul 5.
Pasul 5 : mersul înapoi
(a) )βj , A(α, i , b
( )γ αk , B ' , i , q
unde este produc ția cu num ărul β → A j
Automate, limbaje și compilatoare 106
stabilită la început, al c ărei membru drept este un sufix al lui αβ este și
are numărul ; în acest caz ' Bβ →
k ' 'βααβ= . După efectuarea acestui pas se merge la
pasul 1.
(b) () γ αj , A , n , b+1
() γαβ +, , n , b 1
unde este produc ția cu num ărul β→A j și nu exist ă nici-o alt ă alternativ ă de
reducere pentru αβ . Apoi, se merge la pasul 5.
(c) ()γj , , i , bαA
() γαβ + s , a ,i i , q1
cu este produc ția cu num ărul β → + ≠ ; n i1A j și nu există nici-o alternativ ă de
reducere pentru αβ. Apoi, se merge la pasul 1.
(d) () γs , i , bαa ,
() γ α −, ,1i , b
Deci, se renun ță la trecerea lui a pe banda ; suntem cu o pozi ție în urm ă pe
banda de intrare și rămânem la pasul 5. 1B
II.3.2.3. Algoritmul Cocke -Younger – Kasami (CYK)
Acest algoritm face trece rea de la analiza global ă a lui wna … a a2 1= la
analize locale; timpul de execu ție este de ordinul iar memoria necesar ă este de
ordinul , unde n este lungimea lui . Ideea de baz ă este de a purta pe
cuvântul de analizat dou ă paranteze, una stâng ă notată cu i și alta dreapt ă notată
cu 3n
2n w
j, în aș a fel încât fiecare por țiune din poate fi inclus ă între aceste
paranteze și poate constitui obiect de analiz ă, independent de celelalte por țiuni ale
cuvântului . Fiecă rei pereche ce corespunde porț iunii , îi
atașăm o mul țime de simboluri neterminale w
w ) j , i (1− +j ia ……..ia
[]j,i T astfel încât []j, i T A∈ dacă și
numai dac ă A
1− +j ia1+i i… a a . Evident, dacă []n ,1TS∈ înseamn ă că
S
na …
1=a a2 1 și deci . ) G ( L
[]j , i T
1w∈
Am pus în eviden ță două probleme :
a) construc ția unei mul țimi ce reprezintă structura local ă a cuvântului
; 1 1 − + +j i i ia … a a
b) construc ția unui algoritm car e pentru cuvântul să genereze o analiz ă
pornind de la structurile locale. w
Le analiz ăm pe rând.
a) Pentru și avem urm ătoarele mulț imi n …, , , i2 =j
Automate, limbaje și compilatoare 107
[]{ A / A , i T=1
}ia iar pentru avem 1>j
[]{ A / A j , T=1
}ja … a a2 1
[]{ A / A j , i T=
}1 1 − + +j i i ia … a a
………………………………………………………
[] { A / A j , j n T= + −1
}n j na … a1+ −
Mulțimile de mai sus se organizeaz ă într-un tabel astfel
[][][] []
[] [] [ ]
[] []
[] ⎥⎥⎥⎥⎥⎥
⎦⎤
⎢⎢⎢⎢⎢⎢
⎣⎡
− −−−
=
n , Tn , T n , T, n T … , T , T, n T , n T … , T , T
T
11 2 1 12 1 2 2 2 11 1 1 1 2 1 1
Algoritmul se aplic ă pentru gramatici f ără ε – produc ții și în form ă
normală Chomsky. În acest caz prima linie din tabelul T devine
[](){} n … , , i , P a A / A , i Ti 2 1 1 = ∈ → = .
Considerăm cazul general al liniei j, adică
[]{ A / A j , i T=
}1 1 − + +j i i ia … a a . Dacă A
1 1− + +j i i ia … a a , atunci avem și
A
BC
1 1− + +j i ia …ia a , adică există un k astfel încât
A
BC
C a …k i i1 1 − + + a ai
1− +j i ka …1 1 + + i i i a a … a a− +k i . Adic ă, pentru
m u lțimea jk< 1≤ []j , i T
[] k− poate fi definită în func ție de mulțimile deja construite
și ; deci [k ,] T i T j , k i+
[] [][] {} k j , k i T C , k , i T B , P ) BC A /( A j , i T−+∈ ∈∈ → = .
Procedeul descris poate fi u șor transpus într-un algoritm.
b) După ce a fost construit tabelul T , analiza sintactic ă se poate efectua conform
următorului algoritm
Algoritmul 3.3.
Intrare : o GIC în form ă normală Chomsky , ()S , P , , N GΣ= având producț iile
numerotate de la 1 la , un cuvânt de intrare pna … a a w2 1= și tabelul T al
mulțimilor . []j , i T
Ieșire : analiza sintactic ă la stânga a lui w sau mesajul ,, eroare “.
Metoda: Se folose ște rutina pentru a genera un arbore de derivare (A , j , i gen)
Analiză
sintactică de
tip local
Automate, limbaje și compilatoare 108
stângă corespunzător deriva ției A
1 1− + +j i i ia … a a
P A→. Rutina este definită astfel :
1) Dacă și a m-a produc ție din este , atunci se emite num ărul
. 1=jia
m
2) Dacă și este cel mai mic num ăr întreg, 1>j k j k<≤1 , astfel încât pentru
, și este produc ția cu num ărul , atunci se
emite și se execut ă și apoi []k C, i T B∈
m[] k j , k− + ∈
(k , i geni T BC A
)→ m
B , ( )C , k j , k i gen−+ .
Dacă se execut ă iar dacă [n , T S1∈] (, n ,)S gen1 []n , T S1∉ se emite mesajul
,,eroare “.
Algoritmul analizei locale
Automate, limbaje și compilatoare 109
Teme Curs
Teste Autoevaluare
1. Fie gramatica { }{} ( )P , E , ) , ( , a *, , , ' T , ' E , F , T , E G + = unde P const ă din
producțiile
1. ' TE E→
2. ' TE ' E+ →
3. ε →' E
4. ' FT T→
5. ' FT * ' T→
6. ε →' T
7. a F→
8. ) E ( F→
Efectuaț i analiza sintactic ă descendent ă a cuvântului a ……….. 3 puncte
2. Fie {} { } { } () E , , , , , , , ) , ( , * , , a , F , T , E G6 5 4 3 2 1 + =
1. 4. T E E+ → F T→
2. 5. T E→ ) E ( F→
3. 6. F * T T→ a F→
Se cere analiza sintactic ă ascendent ă a cuvântului a a w∗= ….. 3 puncte
3. Consider ăm gramatica cu producț iile ( S , P , , N GΣ =)
. a A . AS A . SA A .b S . AS S . AA S
→ → →→ → →
6 5 43 2 1
ș i cuvântul de intrare . Se cere abaab w=
a) Tabelul de analiz ă CYK……………………………………… 1.5 puncte
b) Analiza sintactic ă de tip CYK…………………………………1.5 puncte
Oficiu…………………………………………………………………….1 punct
Automate, limbaje și compilatoare 110
Răspunsuri
1. ( E , , , qε1 $)
( ' TE , E , , q11 $) ( cazul 1 )
( ' E ' FT , T E , , q1 1 1 $ ( cazul 1 ) )
( ' E ' aT , F T E , , q1 1 1 1 $ ( cazul 1 ) )
( ' E ' T , a F T E , , q1 1 1 2 $ ( cazul 2 ) )
( ' E ' FT * , ' aT F T E , , q1 1 1 1 2 $ ( cazul 1 ) )
( ' E ' FT * , ' aT F T E , , b1 1 1 1 2 $ ( cazul 4 ) )
( ' E , ' aT F T E , , q2 1 1 1 2 $ ( cazul 6a ) )
( ' TE , ' E ' aT F T E , , q+2 2 1 1 1 2 $ ( cazul 1 ) )
( ' TE , ' E ' aT F T E , , b+1 2 1 1 1 2 $ ( cazul 4 ) )
( , ' E ' aT F T E , , q2 2 1 1 1 2 $( cazul 6a ) )
() ε, ' E ' aT F T E , , t2 2 1 1 1 2 ( cazul 3 )
Deci, analiza sintactic ă la stânga a cuvântului a este
. () 147632 2 1 1 1=' E ' aT F T E h
2. ()ε$, , , q1
() s , a $ , , q 2
() s , F $ , , q6 2
() s , T $ , , q46 2
() s , E $ , , q246 2
() s s *, E $ , , q246 3
() s ss , a * E $ , , q246 4
() s ss , F * E $ , , q246 6 4
() s ss , T * E $ , , q246 46 4
() s ss , E * E $ , , q246 246 4
() s ss , E * E $ , , b246 246 4
() s ss , T * E $ , , b246 46 4
() s ss , F * E $ , , b246 6 4
() s ss , a * E $ , , b246 4
() s s *, E $ , , b246 3
Automate, limbaje și compilatoare 111
() s , E $ , , b246 2
() s s *, T $ , , q46 3
() s ss , a * T $ , , q46 4
() s ss , F * T $ , , q46 6 4
() s ss , T $ , , q46 36 4
() s ss , E $ , , q46 236 4
() s ss , E $ , , t46 236 4
și 23646 46 236= =γ ) s ss ( h ) ( h .
3. a)
A S A A S
A,S A S A,S
A,S S A,S
A,S A,S
A,S
b)
Deoarece []5 1, T S∈ , . Pentru a ob ține arborele de derivare
chemăm rutina . Găsim ) G ( L w∈
()S , , gen5 1 [][]4 2 1 1, T A , , T A ∈ ∈ și ()P AA S∈ →.
Emitem 1 ( num ărul produc ției A AA→ ) și chemăm ()A ,1, gen1 și .
dă producția 6 . Deoarece ()A , , gen4 2
(A , , gen1 1) []1 2, T S∈ , []3 3, T A∈ și este
producția cu num ărul 4 , emite 4 și cheamă SA A→
()A , ,4 2 gen ()5 1, ,2gen urmată de
. Continuând în acest fel se ob ține 164356263 ; aceste secven țe de
reguli dau un arbore de derivare stâng ă pentru (notăm faptul că gramatica este
ambiguă ). (A , , gen3 3)
w
Rezumat: S-au prezentat algoritmi generali de analiz ă sintactic ă
Lucrari Practice (Laborator/Seminar)
Automate, limbaje și compilatoare 112
Conținut Laborator/Seminar
Implementarea unui algoritm de analiz ă sintactică din cei trei prezenta ți.
Teme Laborator/Seminar
1. Implementa ți unul din algoritmii generali de analiz ă sintactică
Rezumat: implementarea unui algoritm de analiz ă sintactic ă
Automate, limbaje și compilatoare 113
Notații
Automate, limbaje și compilatoare 114
Curs 8 Analiza sintactic ă (II)
Descriere Generală
Se prezinta algoritmi de analiz ă sintactică determini ști care
– iau decizii privind un anumit num ăr de simboluri spre dreapta și parcurg
secvența de analizat o singur ă dată
– funcționează pe baza unor rela ții între simbolurile gramaticii (numite de
precedență) care permit determinarea p ărții reductibile
Obiective
– cunoaș terea a trei algoritmi determini ști de analiză sintactică
– cunoaș terea unor posibilit ăți de eficientizare a analizei deterministe
Cuprins
II.3.3. Analiza sintactic ă de tip LL
II. 3.4. Analiza sintactic ă de tip LR
II.3.5. Analiza sintactic ă de tip preceden ță
II. 3.5.1. Analiza sintactic ă a gramaticilor de preceden ță simplă
II.3.5.2. Analiza sintactic ă a gramaticilor de preceden ță slabă
Conținut Curs
II.3.3. Analiza sintactic ă de tip LL
Dăm un algoritm de analiz ă sintactică pentru gramatici de tip ()1≥k , k LL .
Defini ția 3.1. F i e ()S , P , , N GΣ= o GIC. Pentru fiecare
definim funcț iile , numite tabele k *Lși N AΣ ⊆ ∈ L , AT ()k LL asociate cu A și
L , astfel :
(1) ”eroare” dac ă nu exist ă nici-o produc ție =) u ( TL , A α→A astfel încât
L uk⊕ ∈ ) ( PRIMkα .
(2) ( >) <α → =m L , A Y …, , Y , Y , A ) u ( T2 1 dacă există o unic ă producție A→α
astfel încât . L ) ( PRIM uk k⊕ α ∈Curs 8
Durata :
2 ore
Definiția
tabelelor
L , AT
Automate, limbaje și compilatoare 115
Dacă N B , m , x B … B x B xi m m ∈≥ = α 02 1 1 0 și *
ixΣ∈ , atunci
. se nume ște mulțimea local urm ătoare a
lui . D a că atunci() L x B … x B xk m m i i i k⊕+ +1 1 iY
0=mPRIM Yi=
iB ()∅→ =A ) u ( TL , A ,α .
(3) este nedefinit ă dacă există cel puț in două produc ții
astfel încât )u ( TL , A
/ /α α2 1 n/ … A α → 2 1 ≥≤≤⊕ ∈ n , n i , L ) ( PRIM uk i kα .
Această situație nu apare dacă este G()kLL .
Intuitiv, eroare spune că nu este posibil ă nici-o derivaț ie de
forma =) u ( TL , A
Ax
uv pentru nici-un L x∈ și . Când
există exact o produc ție *vΣ ∈
(< α …, , Y , Y ,2 1)> → =m L , A Y ) u ( TA α→A care poate fi
utilizată la primul pas al deriva ției Ax
uv pentru orice Lx∈ și .
Fiecare mul țime dă toate prefixele posibile de lungime cel mult k, formate
din terminale, care pot urma un șir derivat din *vΣ ∈
iY
Bi când utiliz ăm produc ția
, unde în orice deriva α → A B x B1 1 0 m …2 mx B x= α ție de forma
Ax
xα
uv x , cu . L∈
Algoritmul 3.4. – de constr uire a tabelelor LL
Intrare : o GIC ()S , P , , N GΣ = de tip ()k LL
Ieșire : mulțimea T a tabelelor ()k LL
Metoda :
Pasul 1. Se construie ște și se iniț ializează Tε, ST T=0 {}0T= .
Pasul 2. Pentru fiecare tabel ()k LLT cu intrarea
) Y …, , Y , Y , x B … x B x A ( ) u ( Tm m m > < → =2 1 1 1 0
m i≤ ≤ 1 se adaug ă la T tabelul
pentru dacă el nu exist ă deja în T . iY ,iBT
Pasul 3. Se repet ă pasul (2) pân ă când nu se mai poate ad ăuga nici-un tabel la T .
Analiza sintactic ă , folosind mul țimea de tabele ()k LLeste dată de
algoritmul urm ător.
Algoritmul 3.5.
Intrare : gramatica de tip ( S , P , , N GΣ =) ()k LL și T
Ieșire : tabelul M de analiz ă sintactică
Metoda : M este definit pe (T {}S/ ∪ Σ ∪)k *Σ× astfel :
Construirea
tabelelor L , AT
Automate, limbaje și compilatoare 116
Pasul 1. dacă este produc ția cu num ărul i, m mx B … B x B x A2 1 1 0 → ∈L , AT
) T și
atunci ( < →m mY , x B … x B x B x2 2 1 1 0 > =m L , A Y …, , Y , A ) u ( T2 1 M se define ște astfel
()( )i , x T … x T xm Y , B Y , Bm m 1 01 1u , T ML , A= .
Pasul 2. reducere pentru orice . =) av , a ( M) k *(v1−Σ ∈
Pasul 3. acceptare. ()= ε /, S M
Pasul 4. eroare, în alte cazuri . =) u , X ( M
Configura ția inițială este ()ε/, w , S T0 iar cea final ă este ()πε/, , S
w unde
este cuvântul de analizat iar este analiza sintactic ă la stânga a lui . w
π
Analiza sintactic ă a gramaticilor se simplifică în cazul
()k LL 1=k .
Defini ția 3.7 . O gramatic ă ()S , P , , N GΣ= este ()1LL
dacă pentru orice
neterminal și orice dou ă -produc ții distincte A A α→A și este
verificată condi ția β → A
( )( )∅= ∩ ) A ( URM PRIM ) A ( URM PRIM1 1 1 1 β α .
O formulare mai simpl ă a condi ției de mai sus este: pentru orice reguli
: n/ … / / Aα α α →2 1
1. j i pentru ) ( PRIM ) ( PRIMj i ≠ ∅ = α ∩ α 1 1
2. dacă iα
ε atunci
j i pentru ) A ( URM ) ( PRIMj ≠ ∅ = ∩ α 1 1
Analiza sitactic ă se face cu ajutorul funcț iei
()
()
⎪⎪⎪⎪
⎩⎪⎪⎪⎪
⎨⎧
∈∈ = → ∈∈ = → ∈= =Σ ∈ =
=
) (
zuri în alte ca eroarePRIM iar P i A și ) A ( URM a dac ă ) i , (P i A și ) ( PRIM a dac ă ) i , (a si $ A dac ă acceptarea A dacă reducere
) a , A ( M
α εα αα α αε
111
Analiza
sintactică
()k LL
Analiza
()1LL
Automate, limbaje și compilatoare 117
II. 3.4. Analiza sintactic ă de tip LR
Descriem un algoritm de analiz ă sintactică pentru gramatici , care
furnizează o analiză la dreapta privind simboluri în fa ță și funcț ionând în mod
determinist. ) k ( LR
k
Definiția 3.8. Fie o GIC și S colec ția canonică de
mulțimi de linii . )S , P , , N ( GΣ =
) k ( LRT(A ), tabelul asociat mul țimii ) k ( LR A∈S , este o
pereche de func ții unde >g<, f f este func ția de trecere iar g este func ția
GOTO:
(1) functia f este definite astfel
(a) ) u (f =trecere dacă [ ]∈ββ→ v , . A2 1A , βε2≠ și
()vk 2β EFF u∈
(b) dacă [] i ) u ( f= ∈β →u ., AA și β→A este produc ția cu
num ărul i.
(c) =) ( fε acceptare dac ă []∈ε→., S ' SA
(d) =eroare în alte cazuri. )u (f
(2) funcția g determin ă următorul tabel ce va fi folosit în analiz ă; ea pune în
coresponden ță unui element din Σ∪N un tabel sau eroare: )k (LR
GOTO(()=x g A , x) dacă GOTO( A , x)≠∅
eroare dac ă GOTO( ()=x g A , x)=∅.
Algoritmul 3.6.
Intrare : Mulțimea T de tabele corespunză toare gramaticii ) k ( LR ) S , P , , N ( GΣ=
cu tabelul ini țial (T T=0 A0), A()εG
k=V0 și cuvântul ini țial . *Σ ∈w
Ieșire: Analiza sintactic ă la dreapta dac ă ) G ( L w∈ și „eroare“ în caz contrar.
Metoda : Algoritmul lucreaz ă cu o bandă de intrare, o band ă de ieșire și una
pushdown. Configura ția inițială este ) , w , T (ε0 . Se execut ă pașii (1) și (2) până
când se obț ine un ră spuns de acceptare sau de eroare.
Pasul 1. Se determin ă (porțiunea din banda de intrare r ămasă de citit). k PRIM u=
Pasul 2. Fie linia înscrisă în vârful benzii pushdown; > =<g , f Ti
(a) Dac ă =) u ( f trecere, atunci primul simbol disponibil x de pe banda
de intrare se trece în vârf ul benzii pushdown. Calculează jT) x ( g= și înscrie T j
Funcții LR
Automate, limbaje și compilatoare 118
în vârful benzii pushdown și apoi treci la pasul (1).
(b) Dac ă i ) u ( f= și este regula i din P, atunci șterge α → A α2
simboluri de pe banda pushdown și înscrie i pe banda de ie șire. Fie
tabelul rămas în vârful benzii pushdown; determin ă ,
înscrie pe banda pushdown pe > =<j j jg , f T ' T ) A ( gj=
'AT și mergi la pasul (1). Dac ă =) A ( gj eroare,
opreș te algoritmul și cheamă, eventual, o rutin ă de tratare a erorii.
(c) Dac ă = eroare, opre ște algoritmul și cheamă, eventual, o rutin ă
de tratare a erorii. ) u ( f
(d) Dac ă = acceptare, opre ște algoritmul și emite ) u ( f π~, unde π este
secvența de pe banda de ie șire.
În locul analizei LR(1), se preferă analiza LALR(1 ), bazată pe gramatici
LALR (în englez ă lookhead LR grammars). Ea este mai avantajoas ă deoarece
tabelul LALR(1) este mai mic în compara ție cu cel LR(1). De asemenea,
gramaticile LALR(1) acoperă o clasă mare de limbaje ce includ practic toate
construcțiile sintactice folosite în lim bajele de programare cunoscute.
Fie } și ] a ., A {[i α → = A ] b ., A {[j α→=A } două elemente ale
colecției canonice de linii LR(1). Liniile din cele dou ă mulțimi au acela și nucleu,
dar diferă prin ș irul de anticipare ( a și respectiv b). După reducere, în funcț ie de
elementul din vârful stivei și de simbolul de intrare, se ajunge în st ări diferite.
Dac ă se renunță la verificarea simbolului de intrare, cele dou ă mulțimi de
linii LR, și sunt echivalente; putem să le înlocuim cu o nou ă mulțime
. Mai general, dou ă mulțimi din colec ția canonic ă LR(1)
pot fuziona dac ă au acelea și nuclee ale elementelor componente. Repetând
această operație până când nu mai exist ă stări cu nuclee identice, ajungem la un
tabel LR(1). Deoarece funcț ia GOTO depinde doar de nucleu, toate referirile la
și din definirea func ției g vor fi înlocuite prin . iA
A→jA
b / a .,]} {[j , i α = A
jTiT
j , iT
II.3.5. Analiza sintactic ă de tip preceden ță
II. 3.5.1. Analiza sintactică a gramaticilor de preceden ță simplă
Plecând de la rela țiile de preceden ță trebuie stabilit mai întâi când are loc
o trecere a unui simbol de pe banda de intrare pe banda pushdown și când are loc
o operație de reducere.
Analiza LR
Analiza
LALR(1)
Automate, limbaje și compilatoare 119
Algoritmul 3.7
Intrare: o gramatic ă de preceden ță simplă ) S , P , , N ( GΣ= cu produc țiile
numerotate de la 1 la p.
Ieșire: funcțiile și f g.
Metoda : Simbolul marcheaz ă sfârșitul benzii pushdown și ultimul
simbol de pe banda de intrare. Func ția depinde de simbolul din vârful benzii
pushdown și de cel curent de pe banda de intrare; ea este definit ă astfel: ) N ( $Σ ∪ ∉
f
a) , dacă trecere ) a , X ( f= a X sau a X⋅= ⋅ <
b) , dacă reducere ) a , X ( f= a X> ⋅
c) acceptare ,$) S ( f=
d) în alte cazuri. eroare ) a , X ( f=
Regula c) este prioritar ă față de regulile a) și b) când S X= și $ a=
Funcția nu depinde de conț inutul benzii de intrare; ea depinde numai
de simbolurile din vârful benzii pushdown ce formeaz ă partea reductibil ă, plus un
simbol la stânga: g
a') i ) , X X X ( gk k =ε+ 1 1L dacă pentru j j k k X X , X X⋅
+ + = ⋅ <1 1 k j<≤1 și
este producț ia cu num ărul i. 1X XkL→A
b') în alte cazuri. eroare ) , ( g= ε α
Deci f este definită pe {$}) ( {$}) N ( ∪Σ×∪Σ∪ iar este definită pe
. Algoritmul de analiz ă foloseș te o bandă pushdown pe care $
arată capătul din stânga, o band ă de intrare pe care $ arată capătul din dreapta și
o bandă de ie șire. Deci, o configuraț i e e s t e d e f o r m a :
unde: g
*{$})
aL1N (∪ Σ ∪
, X X ($mL1 ) i i $, an qL1
– reprezint ă conținutul benzii pushdown cu în vârf; mX X $L1 mX
– este porțiunea din banda de intrare r ămasă de citit, iar este simbolul
curent; qa aL1 1a
– indică secvența regulilor de produc ție utilizate pentru a reduce cuvântul
inițial la . ni iL1
q m a a X XL L1 1
Pentru ca leg ătura dintre transformarea configura țiilor și funcțiile și f g
să fie mai clară , vom considera că funcț iile și f g sunt extinse astfel:
Funcțiile de
precedență
simplă
Automate, limbaje și compilatoare 120
} acceptare , eroare , reducere , trecere { {$}) ( V : f* *→ ∪ Σ ×
} eroare , p , , , { {$}) ( V : g* *L2 1→ ∪ Σ × ,
unde . {$} N V∪ Σ ∪ =
Trecerea de la o configura ție la alta se define ște astfel:
(1) dacă trecere ) aw , ( f=α atunci ) , aw , (πα
) , w , a (πα ;
(2) dacă , reducere ) w , ( f= α () i w , g=α și β→A este produc ția cu num ărul
atunci (i
) , w ,π α
γβ = α cu ,π γ) i , w , A ( ;
(3) dacă atunci acceptare) w , ( f= α ) , w , (πα
acceptare
(4) ) , w , (π α
eroare în alte cazuri.
Dacă ) $, w ($,ε
) $, , S $ (π
acceptare , atunci . w S~π
α⇒
Exemplul 3.2. Consider ăm gramatica din Lec ția 5. Funcț iile și f g se deduc
imediat urm ărind tabelul prezentat în acest exemplu. S ă efectuăm analiza
sintactică a cuvântului . Avem: babaacacw=
) $, babaacac ($,ε
) $, abaacac , b ($ε
) $, baacac , ba ($ε
) $, baacac , bA ($3
) $, aacac , bAb ($3
) $, acac , bAba ($3
) $, acac , bAbA ($33
) $, cac , bAbAa ($33
) $, cac , bAbAA ($333
) $, ac , bAbAAc ($333
) $, ac , bAS ($ 3331
) $, c , bASa ($ 3331
) $, c , bAA ($ 33312
) $, , bAAc ($ 33312
) $, , S ($ 333121
acceptare
deci și . 333121= π w S~π
α⇒
Analiza de
precedență
simplă
Automate, limbaje și compilatoare 121
II.3.5.2. Analiza sintactică a gramaticilor de preceden ță slabă
Urm ătoarea teorem ă arată cum se alege regula folosit ă pentru reducere.
Teorema 3.1. Fie o gramatic ă de preceden ță slabă,
și . Dacă )S , P , , N ( GΣ =
wX w Cβ δ ⇒ P ) B (∈ β → $ S $*γ⇒ P ) X A (∈βα→ , atunci ultima
producție folosită în derivarea de mai sus nu este β→B .
Demonstra ție. Presupunem c ă ultima producț ie folosită a fost .
Atunci, avem . Conform teoremei 7.6 din I, avem β → B
w X Bw X w B $ S $*β δ ⇒ δ = γ⇒
B X⋅ < sau BX⋅=, ceea ce este în contradic ție cu defini ția gramaticilor de
precedență slabă.
Din aceast ă teoremă rezultă că într-o gramatic ă de preceden ță slabă, odată
izolată limita dreaptă a părții reductibile, reducerea este determinat ă de produc ția
a cărei cea mai lung ă parte dreapt ă filtrează vârful benzii pushdown. În cazul
când condi ția (1) din defini ția preceden ței simple (defini ția 7.17 din I) nu este
satisfăcută, gramatica poate fi modificat ă astfel încât s ă fie eliminat conflictul. De
exemplu, dac ă YX⋅= și Y X> ⋅ atunci YX⋅= înseamn ă că există producția
βαY X A→ . Eliminăm relația YX⋅= astfel:
– înlocuim pe X cu un nou neterminal B; deci produc ția βαY X A→ devine
βαY B A→ ;
– adăugăm la produc țiile existente produc ția . X B→
Modific ările înlătură conflictele, dar tr ebuie verificat dac ă se mai p ăstrează
proprietatea de unic invertibilitate.
Exemplul 3.3. Fie gramatica cu producț iile:
E , F / E F) F ( a / ) E/( a E
→→
Avem și . Dacă înlocuim și adăugăm
, conflictul dispare. Dar, noua gramatic ă: ) E⋅= ) E> ⋅ ) A ( E cu ) E ( E→ →
E A→
Realizarea
precedenței
slabe
Automate, limbaje și compilatoare 122
E AE , F / E F) F ( a / ) A /( a E
→→→
nu mai este unic-invertibil ă datorită producțiilor și . În cazul
gramaticii de mai sus, o solu ție mai bun ă constă în evitarea rela ției E F→ E A→
) E>⋅,
datorată lui , astfel: ) F⋅=
E , F / E F)E, F ( a / ) E( a / ) E/( a E
→→
Acum avem peste tot , dar mai sunt și alte conflicte ce trebuie eliminate:
și sau (și . E=⋅)
F( E (⋅= E (⋅ <⋅= F⋅ <
Automate, limbaje și compilatoare 123
Teme Curs
Teste Autoevaluare
1. Consider ăm gramatica cu produc țiile
ε →→→→
A .b A .bAba S .aAaa S .
4321
Ș tiind că este LL(2), să se efectueze analiza sintactic ă a cuvântului
………………………………………………………….………………… 5 puncte bbba w=
2. Fie gramatica {}{} () S , P , f , e , d , c , b , a , C , B , A , S G = unde produc țiile sunt :
1. aAbc S→
2. BA A→
3. ε → A
4. dcCe B→
5. fa B→
6. cC C→
7. ε → C
Să se verifice c ă este LL( 1) și să se efectueze analiza sintactic ă a cuvântului
………………. …………………………………………………………..4 puncte abc w=
Oficiu………………………………………………………………………. 1 punct
Automate, limbaje și compilatoare 124
Răspunsuri
1. a) Construim mai întâi mulț imea de tabele T.
…………………………………………………………………………………….. 3 puncte
Deoarece calculăm () P aAaa S∈ → (){}{ } ab , aa aAaa PRIMk =ε⊕2 ;
deoarece calculăm () P bAba∈ → S (){}{}bb bAba PRIM =ε⊕2 2 .
Atunci , unde ( Y , aAaa S ) aa ( T→ =0 ) {}{}aa ) aa ( PRIM Y=ε⊕ =2 2
{}ε .
Continuând în acest mod ob ținem tabelul =, ST T0
u Produc ția mulț imile urm ătoare
aa
ab
bb S → aAaa
S → aAaa
S → bAba { aa}
{aa}
{ba}
Deoarece adăugăm la T tabelul {}( aa , aAaa S ) aa ( T→ =0 ){}aa , AT T=1
u Produc ția mul țimile urm ătoare
ba
aa A → b
A → ε ∅
∅
Deoarece , adăugăm la T tabelul {}( ba , bAba S ) bb ( T→ =0 ){}ba , AT T=2
u Produc ția mul țimile urm ătoare
ba
bb A → ε
A → b ∅
∅
b) Construirea tabelului M ……………………………………………………… 1.5 puncte
aa ab a ba bb b ε
0T 11, aa aT 11, aa aT 22, ba bT
T ε , 4 b ,3 1
T2 ε , 4 b , 3
a R R R
b R R R
$ A
Automate, limbaje și compilatoare 125
unde R înseamn ă “reducere” iar A “acceptare”.
c) Analiza……………………………………………………………………… 0.5 puncte
()ε /, bbba , S T0
() 22 , bbba , S ba bT/
( )22 , bba , S ba T/
( )23, bba , S bba/
() 23, ba , S ba/
() 23, a , S a/
()23, , Sε /
deci π = 23.
2. a) verificarea condi ției….……………………………….……….. 1 punct
Deoarece , {}a ) aAbc ( PRIM=1 {}f , d ) BA ( PRIM=1 , {}ε =ε) ( PRIM1 ,
{}d ) dcCe ( PRIM=1 {}f ) fa ( PRIM=1 , {}c ) cC ( PRIM =1 ș i
, {}b=) A ( URM1 {}b ) B ( URM=1 , {}e ) C ( URM=1 rezultă că gramatica
este . (1LL)
b) tabelul …………………………………………………………………………….. 2 puncte
a b c d e f ε
S (aAbc,1)
A (ε,3) (BA,2) (BA,2
B (dcCe,4) (fa,5)
C (cC,6) (ε,7)
a R
b R
c R
d R
e R
f R
$ A
c) analiza …………………………………………………………………………. 1 punct
() ε, abc $, S
() 1, abc $, aAbc
() 1, bc $, Abc
() 13, bc $, bc
Automate, limbaje și compilatoare 126
() 13, c $, c
()13, $,ε
acceptare.
Rezumat: S-au descris algoritmi determini ști de analiza sintactic ă
ascendent ă si descendent ă
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se vor implementa doi algoritmi de analiz ă sintactică corespunzator celor două
tipuri: ascendent și descendent
Teme Laborator/Seminar
1. Implementa ți analiza sintactic ă de tip preceden ță simplă
2. Implementa ți analiza sintactica LL(1)
Rezumat: se implementează algoritmii de tip preceden ță și LL(1)
Automate, limbaje și compilatoare 127
Automate, limbaje și compilatoare 128Notații
Automate, limbaje și compilatoare
129 Curs 9 Analiza semantic ă
Descriere Generală
Se definesc tipurile de atribute și rolul lor în specificarea semanticii unui
limbaj de programare. Se arat ă modul de utilizare a gramaticilor L-atributate
în specificarea semanticii iar în final se d ă un exemplu pentru un limbaj
concret.
Obiective
– cunoaș terea tipurilor de atribute și a semnifica ției lor
– cunoaș terea rolului gramaticilo r atributate în specificarea semanticii unui
limbaj de programare
Cuprins
II.4.1. Specificarea semanticii limbajelor
II.4.1.1. Specificarea semanticii folosind gramatici cu atribute
II.4.1.2. Specificarea semantic ii folosind gramatici L-atributate
II.4.2. Model de analiz ă semantică
Conținut Curs
II.4.1. Specificarea semanticii limbajelor
Analiza lexical ă și cea sintactic ă extrag structura programului surs ă.
Analiza semantic ă completeaz ă structura sintactic ă cu valorile atributelor
asociate componentelor acest ei structuri. Pe baza valorilor atributelor, se
realizează , pe considerente semantice, corectitudinea programului surs ă și se
alcătuiește codul intermediar echi valent. Rezolvarea acestor dou ă sarcini
necesită, de obicei, mai multe parcurgeri ale arborelui de derivare. Num ărul
acestor parcurgeri poate fi fix sau variabil în func ție de structura programului
analizat. Prima situa ție este preferabil ă și, de obicei, prin modifică ri ale
definiției limbajului sau impunerea unor restric ții, numărul parcurgerilor poate fi
limitat, putându-se ajunge la situa ția ideală: o singură parcurgere.
Num ărul de parcurgeri rezult ă din ordinea de evaluare a atributelor și este Curs 9 Durata :
2 ore
Generalit ăți
influențat de resursele de memorie di sponibile. Pentru a economisi spa țiu de
memorie, arborele de derivare nu este exp licit construit; în locul lui se prefer ă
arborele sintactic sau forme echivalente acestuia. În cazul an alizei într-o singur ă
trecere, informa țiile privind structura programului sunt concentrate în șirul
acțiunilor analizorului sintactic și arborele devine inutil. In practic ă, analiza
semantică se desf ășoară în paralel cu cea sintactic ă, asociind ac țiunilor
analizorului sintactic ac țiuni referitoare la atributel e componentelor sintactice.
Knuth a propus o metod ă de specificare a semanticii limbajelor de
programare, definind înț elesuri ale cuvintel or unui limbaj independent de
context cu ajutorul atri butelor asociate simbolur ilor din arborele de derivare.
II.4.1.1. Specificarea semanticii folo sind gramatici cu atribute
Defini ția 4.1. O gramatic ă cu atribute ()GA constă din:
a) o gramatică independent ă de context ( )S , P , , N G Σ = având produc țiile
numerotate sub forma
pnp p p p X X X X . pK2 1 0→
în care simbolul ini țial S nu apare în partea dreapt ă a nici unei produc ții;
b) o mulț ime de atribute . Fiecare atribut tAtA a∈ este caracterizat printr-o
mulțime de valori la fel cum un tip de date este caracterizat prin mul țimea
valorilor sale. Fiec ărui simbol ()a V
Σ∪ ∈N X îi corespunde o mul țime finită de
atribute A formată din două m u l țimi disjuncte S ()X ()X și M()X, numite
mulțimea atributelor sintetizate și respectiv mo ștenite ale lui X. Un atribut poate
reprezenta o entitate oarecare: o valoare numeric ă, un tip, un câmp de caractere,
o adresă de memorie, etc. Atributele din A ()X îns c simbolul oț
Automate, limbaje și compilatoare
130 es X în toate
producțiile în care acesta apare.
c) o mul țime de reguli semantice, folo site pentru evaluarea fiec ărei
producții: F
– pentru un atribut sintetizat, valoarea sa se calculeaz ă î n f u n c ție de valorile
atributelor asociate fiilor acestui nod
S.a
s1.a1 sk.ak …
Gramatic ă cu
atribute
Automate, limbaje și compilatoare
131
ks s SL1→ este regula de produc ție
a = atributul sintetizat asociat lui S și se calculeaz ă în func ție de atributele
asociate respectiv lui : ka , ,Ka1 kS , S1,K ( )ka , , a f aK1 =
Simbolurile terminale nu pot avea atribute sintetizate.
– pentru un atribut mo ștenit, valoarea se calculează utilizând valor ile atributelor
asociate fra ților sau părin ților acestui nod
S.a
s1.a1 sk.ak … si.ai …
ks ……. s S1→ este regula de produc ție
ia= atribut mo ștenit asociat lui ; is ( )k i i i a , , a , a , , a , a f aK K1 1 1 + −=
Dacă existența atributelor sintetizate rezult ă din faptul că înțelesul unei
componente sintactice rezult ă în primul rând din structura ei, necesitatea celor
moștenite poate fi pus ă la îndoial ă.
Exist ă însă situații când atributele mo ștenite nu pot fi evitate, deoarece
ele capteaz ă influența asupra în țelesului unei componente si ntactice a contextului
în care apare componenta respectiv ă. Este posibil ca num ărul de parcurgeri s ă fie
infinit, aceasta însemnând c ă valoarea unui atribut rezult ă dintr-un calcul în care
este implicat ă ea însăși. Knuth a dat un algoritm de verificare a existen ței unei
astfel de situa ții.
Dac ă este un atribut, asociat nodului , ce depinde de atributul ,
atunci regula semantică pentru trebuie evaluat ă după regula semantic ă ce
defineș te pe c. Interdependen ța dintre atributele sintetizate și cele mo ștenite
asociate nodurilor arborelui de derivare poate fi înf ățișată prin graful de
dependen ță: b a c
b
for fiecare nod din arborele de derivare don
for fiecare atribut a asociat nodului n do
Construie ște un nod în graful de dependen țe pentru a
for fiecare nod din arborele de derivare don
for fiecare regulă semantic ă ( )kc , , c , c f : bK2 1 =
asociat ă producț iei corespunz ătoare nodului n do
for i:=1 to k do
Construie ște o muchie de la nodul
corespunz ător lui la cel corespunz ător lui . ic b
De exemplu, fie o regulă semantic ă pentru producț ia
; această regulă definește atributul sintetizat care depinde de
atributele si . Se construiesc nodurile , și , apoi o
muchie de la l a ș i încă una de la la . Dacă producția
are regula semantic ă ( y . Y , x . X f a . A =
a . A
Automate, limbaje și compilatoare
132 )
XY A→
XY A→a A.
x . X
a . Ax . X y . Y a . A
y . Yy . Y
x . X
( )y . Y , a. A g : x . X = atunci se construie ște o muchie
de la la și încă una de la la . a . A x .X y . Y x . X
Exemplul 4.1.
produc ția regula semanantic ă
2 1E E E+ → val . E val . E : val . E2 1 + =
Cele trei noduri din graful de dependen ță marcate prin • corespund atributelor
și val . E , val . E1 val . E2
Figura 4.2 – Exemplu de graf de dependen ță
II.4.1.2. Specificarea semanticii folosind gramatici L-atributate
Func țiilor semantice, fie ele simple transf eruri de valori fie calcule oricât
de complexe ale valorilor atributelor, li se asocieaz ă acțiuni semantice; astfel
analiza semantic ă devine o înl ănțuire a acțiunilor semantice în ordinea impus ă de
acțiunile sintactice. Simbolurile de ac țiune se intercaleaz ă printre simbolurile din
partea dreapt ă a produc țiilor în func ție de necesit ățile de evaluare și transmitere a
atributelor. De exemplu, produc ția poate fi completat ă cu simboluri de
acțiune astfel:
XYZ A→
TZ @ XY A → , unde nota ția @ introduce un simbol de actiune.
Graf de
dependen ță
Automate, limbaje și compilatoare
133 ) Defini ția 4.2. Fie o GIC și ( S , P , , N G Σ = Ω o mulțime de simboluri
(numite de acț iune) astfel încât ( ) . N ∅=Σ∪ ∩ Ω Atunci:
a) Fie tA o m u l țime de atribute, fiec ărui atribut tA a∈ corespunzându-i o
mulțime de valori ()a V. Pentru fiecare simbol Ω∪Σ∪ ∈N X există o
mulțime de atribute asociate A ()tA X⊂ . A()=X M()∪X S()X; ∈m
M()X se numește atribut moștenit al lui X iar s∈ S()Xse numește atribut
sintetizat al lui X.
b) Pentru fiecare produc ție din există o rescriere numit ă producție atributat ă.
În cadrul ei pot s ă apară în partea dreapt ă și simboluri din P
Ω.
c) Pentru fiecare producț ie atributat ă există o mulțime de reguli de calculare a
valorilor atributelor conform regulilor:
c1) valoarea unui atribut mo ștenit ce apare în partea dreapt ă a unei reguli de
producție este calculată în func ție de alte atribute ale produc ției. Pentru
atributele mo ștenite ale simbolului de start se dau valori iniț iale.
c2) valoarea unui atribut sintetizat asociat neterminalului din stânga produc ției
se calculeaz ă în funcție de alte atribute ce apar în regul ă.
c3) valoarea unui atribut sint etizat asociat unui simbol de ac țiune se calculeaz ă
în funcție de alte atribute ale simbolului de ac țiune.
Condiț iile de mai sus definesc o gramatică de traducere atributat ă.
Pentru a exemplifica aceast ă definiție consideră m regula de mai jos, unde
atributele moș tenite sunt precedate de caracterul iar cele sintetizate sunt
precedate de ↑ ↓
:: terms c b a t sterms term↑ ↓ ↑ ↑ ↓+ =
; + c t a s b← ←
Definiția 4.3. O gramatic ă de traducere atributată se numește L-atributat ă
dacă specifica țiile și s e m e nțin nemodificate iar se modifică în: )a )b )c
valoarea unui atribut mo ștenit ce apare în partea dreapt ă a unei reguli de
producție este calculat ă în funcție de atributele mo ștenite ale simbolului din
stânga regulii și atribute arbitrare ale simbolur ilor din dreapta regulii de
producție ce apar la stânga simbolului a că rui apariție de atribut o consider ăm; ) '1c
) '2c valoarea unui atribut sintetizat asoc iat neterminalului din stânga, se
calculează în func ție de atributele mo ștenite ale simbolului din stânga și
Introducerea
simbolurilor
de acțiune
Gramatica L-
atributată
Automate, limbaje și compilatoare
134 atributele arbitrare ale simbolurilor din dreapta ;
) '2c valoarea unui atribut sintetiz at asociat unui simbol de ac țiune se
calculează în funcț ie de alte atribute mo ștenite ale simbolului de ac țiune.
Defini ția 4.4. O gramatic ă L-atributat ă se numește în form ă simplă dacă
cerințele și se modific ă în: ) '1c ) '2c
) "1c valoarea unui atribut mo ștenit asociat unui sim bol din partea dreapt ă este
o constant ă, valoarea unui atribut mo ștenit al simbolului din stânga sau valoarea
unui atribut sintetizat al unui simbol ca re apare la stânga simbolului considerat,
în partea dreapt ă;
valoarea unui atribut sintetizat asociat neterm inalului din stânga este o
constantă, valoarea unui atribut al netermin alului din stânga sau valoarea unui
atribut sintetizat al unui simbol din partea dreapt ă. ) "2c
Fiind dat ă o gramatic ă L-atributată, se poate construi o gramatic ă L-
atributată în formă simplă echivalent ă, prin adăugarea de simboluri de acț iune.
terms @add term :: terms f e d c b, a t s ↑ ↓ ↑ ↓ ↑ ↑ ↓+ =
f t , d e , a c , s b← ← ← ←
Diferența esențială dintre cele dou ă gramatici const ă în înlocuirea regulilor de
evaluare prin simboluri de ac țiune. De exemplu, simbolul de ac țiune
invocă rutina care prime ște ca parametri de intrare atributele mo ștenite
și și genereaz ă ca parametru de ie șire atributul sintetizat add @
c''
''add
b c b d : d+ ← . Este
posibil să se înlocuiasc ă atribuirea explicit ă prin atribuirea implicit ă care se
realizează folosind atribute variabile. De exemplu, produc ția anterioara poate fi
scrisă ca
f d d a , s a f sterms add @ term :: terms↑ ↓ ↑ ↓ ↑ ↑ ↓+ =
Regulile ce guverneaz ă această atribuire sunt urm ătoarele:
1) un atribut mo ștenit, să zicem , situat în partea dreapt ă primește ca valoare
atributul sintetizat sau mo ștenit având acela și nume și situat la stânga lui . a
a
Referindu-ne la regula analizat ă avem:
– atributul mo ștenit din partea dreapt ă primește valoare de la atributul mo ștenit
situat în stânga regulii; s
s
– atributul mo ștenit primește valoare de la atributul sintetizat asociat d d
Gramatica L-
atributată în
formă simplă
simbolului de acț iune . add @
2) un atribut mo ștenit, să zicem , din partea stâng ă moștenește valoarea prin
aplicarea unei producț ii care invoc ă partea stâng ă. De exemplu, atributul moștenit
din stânga regulii 4 prime ște valoare prin aplicarea produc țiilor care conț in a
s
terms în partea dreapt ă.
3) un atribut sintetizat ce apare în partea dreapt ă a unei reguli primește valoare
fie prin aplicarea unei rutine de ac țiune fie prin sintetizarea informa ției produse
prin procesul de construire a arborelui de derivare.
De exemplu, atributul sintetizat d din dreapta produc ției primește valoare prin
invocarea rutinei de ac țiune iar atributul sintetizat din dreapta
primește valoare când add@ f
f e↑
Automate, limbaje și compilatoare
135 terms↓ se unifică eventual cu cuvântul vid și
primește valoarea lui așa cum rezult ă din produc ția 3; f
s
4) un atribut sintetizat din partea stâng ă primește valoare de la atributul
sintetizat cu acela și nume situat în dreapta produc ției. Deci, atributul sintetizat
care apare în stânga produc ției primește valoare de la atributul sintetizat din
partea dreaptă. f
f
Regula urm ătoare este in forma simpl ă
f d d a , s a f sterms add @ term :: terms↑ ↓ ↑ ↓ ↑ ↑ ↓+ =
II.4.2. Model de analiz ă semantic ă
Definim gramatica independentă de context ce define ște limbajul cu care
vom lucra, apoi vom atributa aceast ă gramatic ă. Mulțimea simbolurilor terminale
este T={func, var, endf, rezultat, +, -, *, /, (, ), virgul ă , ; , =, lit, v, n, f} Primele
patru simboluri sunt cuvinte rezervate: (este analogul lui function din
Pascal și servește la definirea unei noi funcț ii), var (se utilizeaz ă la definirea
variabilelor), (indică sfârșitul defini ției unei func ții) și (specific ă
variabila sau parametrul formal a c ărui valoare este returnat ă de funcfunc
endf rezultat
ție).
Următoarele patru simboluri terminale corespund celor patru opera ții aritmetice;
urmează parantezele rotunde și virgula, care servesc la delimitarea șirului de
parametri ai unei func ții. Simbolul punct și virgulă se utilizeaz ă pentru
semnalarea sfârșitului unei instruc țiuni sau a unei declara ții, iar semnul egal
serveș te la delimitarea p ărții stângi a unei atribuiri, de partea dreapt ă a acesteia.
Ultimele patru simboluri au urm ătoarea semnifica ție:
Automate, limbaje și compilatoare
136 – lit corespunde unui literal numeric;
– , v, și corespund fiecare unui identificator. n f
La întâlnirea unui identificator , analizorul lexical returneaz ă simbolul
terminal dacă identificatorul este întâlnit pentru prima dat ă sau nu are înc ă
atributele completate (este înc ă nedefinit), simbolul dacă din tabela de
simboluri reiese c ă este o variabil ă sau parametru formal al unei funcn
v
ții,
respectiv simbolul terminal dacă s-a întâlnit un nume de func ție. f
Mulțimea simbolurilor neterminale este
N={Start, Vars , Func, Corp, Listparform, Sflist1, Atrib, Expr, Termen,
Sftermen, Fact, Sffact, Listparact, Sflist2 }
Simbolul de start este , iar produc țiile sunt urm ătoarele: Start
Corp Func Vars Start . → 1
ε → Vars .2
; 1 3 Sflist n var Vars . →
ε →1 4 Sflist .
; Sflist n , Sflist .1 1 5→
; v rezultat Atrib Corp . → 6
ε → Atrib .7
Atrib ; Expr v Atrib . = → 8
Func endf Corp Func Varsm Listparfor n func Func ; . 9 →
ε → Func .10
ε → m Listparfor . 11
) Sflist n ( m Listparfor .1 12 →
Sfterm Termen Expr . → 13
ε → Sfterm .14
Expr Sfterm . + → 15
Expr Sfterm . − → 16
Sffact Fact Termen . → 17
ε → Sffact .18
Termen Sffact . ∗ → 19
Termen / Sffact . → 20
v Fact .→ 21
Gramatica
limbajului
Automate, limbaje și compilatoare
137 lit Fact .→ 22
) Expr ( Fact . → 23
Listparactf Fact .→ 24
) Sflist Expr ( Listparact . 2 25 →
ε → Listparact .26
ε → 2 27 Sflist .
2 2 28 Sflist Expr , Sflist . →
Un program definit de aceast ă gramatic ă se compune din definirea
variabilelor, a func țiilor și din programul principal care are aceea și sintaxă ca ș i
corpul unei func ții.
Variabilele sunt definite înaintea func țiilor pentru ca ele s ă fie vizibile și în corpul
funcțiilor. Definirea variabilelor începe cu cuvântul cheie var urmat de o list ă de
identificatori, separa ți prin virgul ă, și terminat ă cu punct și virgulă. Corpul unei
funcții (precum și programul principal) const ă dintr-o list ă de atribuiri urmat ă de
cuvântul cheie rezultat care precede un nume de variabilă (sau parametru
formal, care la nivelul sintaxei este echivalent cu o variabil ă). Din produc ția 9
rezultă felul cum se pot defini func țiile: cuvântul rezervat arată că începe o
definiție de func ții; după urmează numele func ției, urmat de lista, eventual
vidă, a parametrilor formali și punct și virgulă. Urmează definirea variabilelor
locale, definirea func țiilor locale funcț iei în curs de definire (func țiile imbricate),
după care urmeaz ă corpul func ției. Definirea unei func ții se termin ă cu cuvântul
rezervat endf . După defini ția unei func ții poate urma o alt ă definiție de func ție;
această funcție va fi la acela și nivel cu prima. Produc ția 10 arat ă că funcțiile
locale pot s ă lipsească. func
func
Produc țiile 13-28 definesc sintaxa unei e xpresii aritmetice. In definirea
sintaxei unei expresii s-a f ăcut deosebire între neterminalele Termen și ;
primul apare în sume și diferen țe iar al doilea în produse și câturi. Aceast ă
deosebire este necesar ă datorit ă priorităților diferite asociate operatorilor
aritmetici. Dac ă nu ar fi fost problema priorit ăților, sintaxa expresiilor aritmetice
s-ar fi putut descrie și cu produc țiile Factor
Sffact Fact Expr )'→ 13
Fact Oper Sffact )'→ 14
ε → Sffact )'15
Automate, limbaje și compilatoare
138 e pu
că este un neterminal
) și introducând produc țiile
va fi -atributată astfel încât atributele și acțiunile
rului de parametri actuali cu num ărul parametrilor
e blocuri, adic ă schimbarea
aloca cțiilor.
ulțimi de valori
lor
în textul surs ă;
ormal ;
că a unui identificator;
icatorilor ad și.
Valorile atributelor sunt: , + Oper )'→ 16
− → Oper )'17
∗ → Oper )'18
/ Oper )'→ 19
car teau înlocui produc țiile 13-20.
În definirea sintaxei limbajului de programare s-a folosit simbolul
terminal lit pe care îl va returna analiz orul lexical de fiecare dat ă când întâlne ște
în textul sursă un literal numeric, adic ă o succesiune de cifre. Acest fapt poate fi
detaliat mai mult la nivelul gramaticii, considerând lit
(notat în continuare cu Lit
7 3 lit Sflit Sfli Lit Sflit Lit → → →
Gramatica precedent ă 6 2 9 5 1 8 4 0
tSflit Sflit Lit Sflit LitSflit Lit Sflit Lit Sflit LitSflit Lit Sflit Lit Sflit Lit
→ → →→ → →→ → →
ε
L
semantice s ă permită :
– verificarea coinciden ței numă
formali, la apelul unei func ții;
– asigurarea regulilor de valabilitate pentru structura d
contextelor și permiterea redefini rii locale a numelor;
– rea memoriei pentru variabilele și parametri formali ai fun
Pentru aceasta s-au definit urm ătoarele m
VAL – corespunde valorii unui literal numeric;
DIM – corespunde num ărului total de parametri și variabilele locale;
OFF – corespunde offsetului în cadrul articolu lui de activare: practic acest offset
este num ărul de ordine al identificatorului în lista concatenat ă a parametri
formali și variabilelor locale ale func ției în ordinea apari ției lor
PAR – corespunde num ărului de parametri formali sau actuali;
TIPV – corespunde tipului va riabilei : variabil ă locală sau parametru f
NIS – corespunde nivelului de imbricare stati
NUME = mulțimea identif mi
() N VAL V= N ) DIM ( V=,
N ) OFF ( V=, N ) PAR ( V=, N ) NIS ( V=, { }par r,va ) TIPV ( V= ;.
Atribu
– atele asociate difer itelor simboluri gramaticale sunt:
OFFStart↑rată numărul de variabile definite la nivelul programului principal;
Valorile
atributelor
Automate, limbaje și compilatoare
139 ei variabile din lista variabilelor locale,
respectiv num ărul
ffsetul și tipul urm ătoarei variabile din list ă, respectiv
numărul total de
–
inițial de parametri actuali (adic ă 0) respectiv
numărul total
numărul de parametri actuali deja analiza ți, respectiv
număr
– arată valoa
– arată tipul, numele și offsetul variabilei, respectiv nivelul de
imbrica
nedefinit nu are alt ă informație completat ă în tabela
de simboluri, decâ
l de parametri formali, num ărul total de
Cu aceste notaț ii, gramatica L-atributat ă este :
.
@ Refă; Vars Func Corp, endf @Exit @Insfunc Func OFF OFFVars↑ ↓ – arată offsetul prim
total de variabile;
OFF TIPV OFFSflist1↑ ↓ ↓ – arată o
variabile;
OFFm Listparfor↑ arată numărul de parametri formali ai func ției;
PAR PARListparact↑ ↓ – arată numărul
de parametri actuali;
PAR PARSflist2↑ ↓- arată
ul total al lor;
VALlit↑rea literalului
NIS OFF NUME TIPVv↑ ↑ ↑ ↑
re statică;
NUMEn↑ – un identificator înc ă
t numele;
NIS DIM PAR NUMEf↑ ↑ ↑ ↑ – arată numele, num ăru
variabile, respectiv ni velul de imbricare.
Corp Func Var Start .o 0, o→ s 1
ε →o o, Vars .2
fa Re ; SflistIns @ n Taie @ var Vars .
o var, , oo , n var,
n o1 o,
1 1 13
+→
@
.4 ε →o , t , o Sflist 1
5o , t ; Sflist Ins @ n , Sflist, oo , n , t
n o , t , o 1 1 1 1 1+ →
Atrib ; v rezultat Atrib Corp .i , o , n , t → 6
ε → Atrib .7
Atrib ; Expr v Atrib .i , o , n , t= → 8
@ n Taie func Func .n → 9 Refă m Listparfor Taie Contex @ @o @ t
oo,1noo,,1
ε → Func .10
ε →0 11 m Listparfor .
, n) Sflist Ins @ n ( m Listparfor .o , par ,o , par
n o 11 12 →
Atributele
asociate
Gramatica L-atributată
Automate, limbaje și compilatoare
140 Sfterm Termen Expr . → 13
ε → Sfterm . 14
Expr Sfterm . + → 15
Expr Sfterm . − → 16
F Sffact act Termen . → 17
ε → Sffact .18
Termen Sffact . ∗ → 19
Termen / Sffact . → 20
i , o ,n , tv Fact .→ 21
vlit Fact .→ 22
) Expr ( Fact . → 23
if Ver @ Listparact f Fact .a , p
a , i , d , p , n 0 24 →
E ) Sflist xpr ( Listparact .p , p p , p 1 1 1 2 25+ →
ε→p , p Listparact .26
ε →p , p Sflist . 2 27
1 1 1 2 2 28p , p p , p Sflist Expr Sflist .+ →
Actiuni
contex t curent la contextul tat ă, pentru a
ura la contextul tat ă, pentru a permite fo losirea numelor din
blocurile înglobat
rează în blocul curent al tabe lei de simboluri o variabil ă
– crează u
r egal cu și cu numărul total de
– verifică dacă numărul parametrilor actuali este egal cu num ărul
celor fo
– determin ă ieșirea din contextul curent în contextul tat ă. le semantice au urm ătorul rol :
Taie @ – taie leg ătura de la blocul
permite redefinirea local ă a numelor;
@Refă- reface legă t
e;
InsNUM , TIPV – inse @OFF , E
de tip TIPV cu numele NUME și offsetul OFF ;
Context @ n context imbr icat, initial vid;
nc @DIM , PAR , NUME – insereaz ă în blocul curent al tabelei de simboluri o func ție
cu numele NUME , cu numărul parametriloInsfu
variabile plus p PAR
arametri formali egal cu DIM ;
Verif @PAR , PAR
rmali;
Exit@
Acțiuni
semantice
Automate, limbaje și compilatoare
141 eme Curs
este Autoevaluare
…1 punct
t
8. are este atributul care trebuie s ă fie obligatoriu prezent?………… 1 punct
Oficiu……………………………………………………………………………………… 1 punct
T
T
1. De cine depinde num ărul de parcurgeri ale arborelui de derivare necesar
pentru calcularea atributelor?………………………………………………….. 1 punct
2. Prin ce metode poate fi modificat num ărul parcurgerilor?………….. 1 punct
3. Care sunt elementele ce definesc o gramatic ă cu atribute?…………. 1 punct
4. Câte tipuri de atribute exist ă și prin ce se caracterizeaz ă?………….. 2 puncte
5. Care atribute nu pot fi eliminate și de ce?……………………………….
6. În ce parte a unei reguli de produc ție se plaseaz ă simbolurile de
acțiune?……………………………. ………………………………………………….1 punc
7. Dați un exemplu de situa ție în care parcurgerea ar borelui de derivare, în
vederea calcul ării atributelor, duce la ciclare?…………………………. 1 punct
C
Automate, limbaje și compilatoare
142 ăspunsuri
de evaluare a atributelor și de resursele de memorie
entă de context, mul țimea atributelor ș i mulțimea
ză utilizând
R
1. De ordinea
disponibile
2. Prin modifică ri ale defini ției limbajului sau impunerea unor restric ții
3. Gramatica independ
regulilor semantice
4. Atribute sintetizate și atribute mo ștenite. Pentru un atribut sintetizat,
valoarea sa se calculeaz ă în funcție de valorile atribut elor asociate fiilor
acestui nod. Pentru un atribut mo ștenit, valoarea se calculea
valorile atributelor asociate fra ților sau părinților acestui nod
5. Atributele sintetizate, deoarece existen ța lor rezult ă din faptul c ă înțelesul
sintactice este dat în primul rând de structura ei
ză atributul are ca argument pe
8. Adresa de memorie
unei componente
6. În partea dreapt ă
7. Funcția care calculea a a
Rezumat: S-au definit no țiunile de atribut, gramatic ă L-atributat ă și s-a
prezentat modul de utilizare a gramatic ii L-atributate pentru specificarea
semanticii unui limbaj; în final s-a dat un exemplu de gramatic ă L-atributat ă
pentru un limbaj de programare.
Lucrari Practice (Laborator/Seminar)
onținut Laborator/Seminar
ă verifice prin tehnici semantice
ansmiterea corect ă a parametrilor formali
C
Se implementeaz ă un program simplu care s
tr
Automate, limbaje și compilatoare
143 eme Laborator/Seminar
semantică pentru verificarea transmiterii corecte a
parametrilor actuali.
T
1. Implementati analiza
Rezumat: se implementează un model de analiz ă semantic ă
Automate, limbaje și compilatoare
144 Notații
Automate, limbaje și compilatoare
145 Curs 10 Generarea codului intermediar
Descriere Generală
Se prezint ă trei forme de reprezentare a codului intermediar: forma polonez ă,
arbori sintactici ș i triplete. Ca model se prezint ă codul intermediat pentru
expresii booleene.
Obiective
– cunoașterea semnifica ției și importan ței codului intermediar
– cunoașterea tipurilor de cod intermediar și a diferen țelor dintre ele
– cunoasterea posibilit ăților de implementare a codului cu trei adrese
– întelegerea modului de genera re a codului cu trei adrese
Cuprins
II.5.1. Forma polonez ă
II. 5.2. Arbori sintactici
II.5.3. Cod intermediar cu trei adrese
II.5.3.1. Triplete
II.5.3.2. Cuadruple
II.5.3.2.1. Expresii booleene
Conținut Curs
Rezultatul anali zei sintactice și semantice const ă dintr-un „fi șier“ conținând
traducerea programului într-un limbaj intermediar. Acesta este mai apropiat de limbajul de asamblare decât de cel surs ă. Astfel, programul es te o succesiune de
operații împreun ă cu operanzii asocia ți. Operațiile sunt în majoritate similare
celor din limbajul de asamblare: opera ții aritmetice, atribuiri, teste, salturi, iar
ordinea lor din program este cea în care se execut ă. Din program lipsesc
declaraț iile, descrierea operanzilor g ăsindu-se în tabela de simboluri. În acela și
timp, codul intermediar se deosebe ște de limbajele de asamblare prin aceea c ă
operanzii nu sunt regi ștri sau cuvinte de memorie, ci referin țe la intrări în tabela
de simboluri. În afara referin țelor propriu-zise, operanzii mai pot con ține și
informații sumare privind natura lor: vari abile simple, variabile indexate, Curs 10
Durata :
2 ore
Generalit ăți
Automate, limbaje și compilatoare
146 )variabile temporare, cons tante, apeluri de func ții sau informaț ii privind modul de
adresare: direct sau indirect. Structura secven ței operațiilor, ca și modul de
reprezentare a unei instruc țiuni sunt dependente de solu ția adoptată pentru codul
intermediar: forma polonez ă, arbori sintactici, triplete, cuadruple.
II.5.1. Forma polonez ă
Acest tip de cod intermediar este foar te utilizat pentru limbaje constituite
în general din expresii aritmetice și structuri de control rudimentare. O expresie în
formă poloneză, sau nota ție postfixat ă se caracterizeaz ă prin aceea c ă operatorii
apar în ordinea în care se execut ă operațiile pentru calculul expresiei. De aceea,
evaluarea unei expresii în form ă poloneză se face parcurgând într-un singur sens
expresia și executând opera țiile ținând seama de aritatea lor. De exemplu,
expresia se traduce în form ă poloneză în (c b a+ ∗ ∗+abc . În parcurgerea ei
spre dreapta întâlnim întâi + care, fiind o opera ție binară , determin ă efectuarea
adună rii b+c . Urmeaz ă ∗ care, precedat de a și de rezultatul lui b+c (să-l
notam cu t), determin ă operația . t a∗
Definiția 5.1 . O expresie în form ă poloneză ( EFP ) se define ște astfel:
1) orice operand este EFP; a
2) daca sunt EFP ș i ne e e, , ,2 1L ∗ este o operatie -ară n ( )1≥n , atunci
este EFP; ∗ne e eL2 1
3) orice expresie format ă altfel ca la 1) și 2) nu este EFP.
Transcrierea unei expr esii aritmetice în form ă polonez ă se face cu
următorul algoritm :
Algoritmul 5.1
Intrare : o expresie aritmetic ă
Ieșire : forma polonez ă postfixată a expresiei aritmetice
Metoda : se definesc priorit ățile pentru operatori :
$ ș i ( au prioritatea 0
+ ș i – au prioritatea 1
∗ și / au prioritatea 2
$ este un simbol special, iar pentru ) nu avem nevoie de priorit ăți.
Definiția
formei poloneze
Automate, limbaje și compilatoare
147 ) Lucrăm cu triplete ( γβ α, ,, unde α este ș irul de intrare, β este stiva de lucru
folosită pentru depozitarea temporar ă a operatorilor iar este ș irul de ieș ire.
Configura ția iniț ială este γ
() ε α$, , iar cea final ă este ( ) εα$, , .
Pasul 1 . () γβα , b , a
() a , b ,γβα dacă a este operand
() γβ α, ab , dacă este operator și a ()()b P a P>
sau ( a=
() b , , aγβ α dacă a este operator și ()()b P a P≤
Pasul 2. () γβ α, b , )
( )γβ α, , dacă ( b=
( )b , , )γβα dacă ( b≠
Pasul 3. ()βγ ε , b ,
() b , ,γβε dacă $ b≠,
unde este prioritatea operatorului ()x P x.
Așa cum am subliniat anterior, avan tajul folosirii formei poloneze ca
limbaj intermediar const ă în proprietatea c ă expresia poate fi evaluat ă printr-o
singură trecere prin textul ei.
Simplitatea algoritmului de evaluare recomand ă folosirea formei
poloneze ca limbaj intermediar în compilare. Dar, în cazul limbajelor de
programare exist ă și alte opera ții ce trebuie traduse în cod intermediar: atribuiri,
teste, salturi, indexă ri, etc. De aici, neces itatea extinderii reprezent ării și la
asemenea opera ții sau folosirii altor forme de reprezentare.
Se pot ad ăuga, de exemplu, um ătoarele opera ții:
a) L goto – operație ce indic ă o instruc țiune de salt din programul surs ă. Acestă
etichetă se află într-o intrare în tabela de simboluri care se actualizeaz ă la un
moment dat cu echivalentul etichetei în forma polonez ă: un index în șirul fpol .
b) A INDEX – opera ție cu num ăr variabil de operanzi reprezentând
indexarea tabloului cu rezultatele expresiilor . Operaț ia INDEX, pe
baza simbolului nE …. E E2 1
AnE ,…, E1
A din vârful stivei, determin ă din tabela simbolurilor num ărul
al dimensiunilor lui și extrage din stiv ă, pentru indexare, cele valori ale
expresiilor. n
A n
c) P PREL – operator cu num ăr variabil de operanzi reprezentând
apelul procedurii nE …. E E2 1
P cu parametri efectivi da ți de expresiile . nE ,…, E1
d) A TDECL – opera ție cu num ăr variabil de operanzi
reprezentând declara ția tabloului n nS I … S I S I2 2 1 1
A. și reprezint ă expresiile ce dau limita jIjS
Algoritmul
formei
poloneze
Automate, limbaje și compilatoare
148 inferioară și respectiv superioar ă pentru dimensiunea j .
II. 5.2. Arbori sintactici
Reprezentarea programului intermediar ca un arbore este forma de
reprezentare cea mai apropiat ă de structura sintactic ă a programului surs ă, fiind
mai indep ărtată de structura program ului obiect. Ea con ține puține elemente noi
față de programul surs ă, fiind o form ă concentrat ă a acestuia. Din aceast ă cauză
reprezentarea arborescent ă este utilă în faza de optimizare a codului. În general,
arborele folosit nu este cel al deriv ării, ci o variant ă a s a c a r e n u c o n ține
redundanțe. Un astfel de arbore se nume ște arbore sintactic sau abstract. În figura
5.1 se prezint ă arborii sintactici ai unei expresii aritmetice și ai unei instruc țiuni
condiționale. Se observ ă că nodurile interioare sunt et ichetate cu operatori, iar
frunzele cu operanzi. Opera țiile nu sunt numai aritme tice, ele pot fi: index ări, select ări,
comparații, atribuiri, salturi, etc. De asem enea, ele pot fi: unare, binare sau
ternare. Aritatea opera țiilor dă numărul de descenden ți ai nodului etichetat cu
operația respectiva. Totu și, în unele cazuri se prefer ă folosirea arborilor binari
care au reprezentarea mai uniform ă și sunt mai u șor de parcurs.
• *
/ \
/ \
• id1 • +
/ \
/ \
id2 • • [ ]
/ \
/ \
• id3 • id4
id1*(id2+id3[id4] )
Figura 5.1
Exemplu de
arbore
sintactic
Automate, limbaje și compilatoare
149 II.5.3. Cod intermediar cu trei adrese
Cel mai adesea, codul intermediar este v ăzut ca o secven ță de instruc țiuni
de tipul , unde și sunt identificatori din program, constante
sau variabile temporare generate de compilator, iar op este o opera ție aritmetic ă
sau logic ă. Instrucțiunile complexe sunt fragmentate în instruc țiuni simple
conținând un singur operator. Variabilele te mporare sunt create pentru a memora
rezultatele intermediare. Codul cu trei adrese poate fi implementat sub form ă de
triplete, triplete indirecte sau cuadruple. C op B : A = B , A C
II.5.3.1. Triplete
Sunt reprezentate prin structuri cu trei câmpuri con ținând operatorul și cei
doi operanzi. Instruc țiunea se reprezint ă printr-o structur ă ale cărei
câmpuri con țin : și . Cele trei câmpuri sunt pointeri c ătre tabela de
simboluri sau c ătre structura tripletelor. Pointerii c ătre structura tripletelor se vor
reprezenta prin numere între paranteze rotunde. C op B : A =
C B , op
Exemplul 5.1. Expresia () D C B : A∗+ = se reprezint ă astfel:
număr
triplet Operator Operand
stânga operand
dreapta
( 0 ) + B C
( 1 ) * ( 0 ) D
( 2 ) := A ( 1 )
În faza de optimizare a codului au loc, frecvent, opera ții de suprimare
sau deplasare a instruc țiunilor cu trei adrese. În caz de deplasare trebuie
modificați toți pointerii c ătre aceste instruc țiuni. Trebuie parcurs ă structura
tripletelor și modificate toate tripletele care utilizeaz ă variabila temporară
asociată tripletului deplasat. Pentru a economisi timp se preferă folosirea
tripletelor indirecte . În acest caz, structurii tripletelor i se asociaz ă o listă de
pointeri, care dau ordinea de execu ție a tripletelor. Când au loc modific ări în
ordinea de execu ție a tripletelor, este suficient s ă se reordoneze numai lista
pointerilor.
Cod
intermediar
sub forma de triplete directe
Automate, limbaje și compilatoare
150 Exemplul 5.2. Expresia () D C B : A∗+ = se reprezint ă prin triplete indirecte
astfel:
Instruc țiuni operator operand operand
stânga dreapta
( 0 ) ( 100 ) ( 100 ) + B C
( 1 ) ( 101 ) ( 101 ) * ( 0 ) D
( 2 ) (102 ) ( 102 ) := A ( 1 )
II.5.3.2. Cuadruple
Cuadruplele sunt structuri cu patru câmpuri con ținând operatorul, cei doi
operanzi și rezultatul. Câmpurile corespunz ătoare operanzilor și rezultatului
pointează către tabela de simboluri. Trebuie, deci, ca variabilele temporare s ă fie
memorate în tabela de simboluri la fel cum sunt memora ți identificatorii unui
program surs ă.
Exemplul 5.3. Expresia ( )D C B : A∗+ = se reprezint ă prin cuadruple
astfel:
operator operand stânga operand
dreapta rezultat
( 0 ) + B C T1
( 1 ) * T 1 D T2
( 2 ) := A T 2
În continuare ne vom ocupa numai de generarea co dului intermediar sub
formă de cuadruple. Instruc țiunile cu trei adrese pe care le utiliz ăm în continuare
sunt :
• instructiuni de atribuire :
– cu operator aritmetic sau logic binar; C op B : A = op
– cu operator aritmetic sau logic unar; Bop : A= op
– B A=:
• instrucțiuni de salt necondi țional:
Cod intermediar
sub forma de
triplete
indirecte
Cod intermediar sub formă de
cuadruple
Automate, limbaje și compilatoare
151 – ; Q goto
• instrucțiuni de salt condiț ional:
– unde oprel este un operator rela țional; dac ă
relația este satisf ăcută se execută instrucțiunea cu trei adrese etichetat ă cu Q; Q goto B oprel A if
• apel de subprograme :
– – specific ă faptul că este parametru; Pa Param Pa
– Call Pr, Np – specific ă apelul procedurii Pr cu Np parametri;
• atribuirea indexat ă:
– și []i B : A= []B : i A=
• atribuirea prin pointeri și adrese:
– și ; B * : A= B : A *=
– ; B Adr : A =
Exemplul 5.4.
A:=B or C T1:=B or C
A:=T1
Prod (A,B) (1) Param A
(2) Param B (3) Call Prod, 2
În tabelul urm ător se dă corespondenț a dintre instruc țiunile cu trei adrese ș i
cuadruple:
Instrucț iunea cu trei adrese Cuadruplul
A:=B op C (op , B , C , A )
A:= op B (op , B , _ , A )
A:= B ( := , B , _ , A )
Param Pa ( Param , Pa , _ , _ )
Call Pr , Np ( Call , Pr , Np , _ )
goto Q ( goto , _ , _ , Q)
If A oprel B goto Q ( oprel , A , B , Q )
Vom exemplifica, în continua re, modul de generare a codului intermediar
Instrucțiuni cu
trei adrese
Automate, limbaje și compilatoare
152 pentru expresii booolene.
II.5.3.2.1. Expresii booleene
Gramatica ce genereaz ă expresii booleene este:
G= ({ E },{id , or , and ,not , oprel , := , ( , ) } , P ,E } cu următoarele
producții :
1. E → E or E
2. E → E and E
3. E → not E
4. E → ( E )
5. E → id
6. E → id oprel id
Reprezentare prin valorile fals și adevărat
Pentru a reprezenta valoarea unei expresii booleene vom folosi valorile 0
pentru fals și 1 pentru adev ărat. Expresiile sunt evaluate de la stânga la dreapta
ținând seama de prioritatea operatorilor: operatorul not este prioritar în raport cu
and, care este prioritar în raport cu or. În acțiunile semantice asociate regulilor
gramaticii, presupunem c ă toți identificatorii sunt de tip boolean. Gramatica cu
atributele și acțiunile semantice asociate sunt :
1) E → E1 or E2 @1
2) E → E1 and E2 @2
3) E → not E1 @3
4) E → ( E1) @4
5) E → id @5
6) E → id1 oprel id2 @6
@1 T := Var_Temp ( )
E.intrare := T
Gen_cuadr (or, E
1.intrare, E2.intrare, T )
@2 T := Var_Temp ( ) E.intrare := T Gen_cuadr (and, E
1.intrare, E2.intrare, T )
@3 T := Var_Temp ( )
Gramatica
Automate, limbaje și compilatoare
153 E.intrare := T
Gen_cuadr (not , E1.intrare , _ , T )
@4 E.intrare := E1.intrare
@5 E.intrare := id.intrare
@6 T := Var_Temp ( )
E.intrare := T
Gen_cuadr (oprel , id1.intrare , id2.intrare , Cuadr+3 )
Gen_cuadr ( := , 0 , _ , T )
Gen_cuadr ( goto , _ , _ , Cuadr+2 ) Gen_cuadr ( := , 1 , _ , T )
Cuadr trimite că tre prima intrare liber ă din tabela de cuadruple. Aceast ă
variabilă este incrementată automat la fiecare crear e a unui nou cuadruplu, adic ă
la fiecare apel al func ției Gen_cuadr( ).
Reprezentarea printr-o pozi ție de atins
Aceast ă metodă, numită și evaluare prin scurt-circuit, permite generarea
unui cod corespunză tor unei expresii ce va fi evaluat ă în funcție de valoarea sub-
expresiilor. Dacă avem expresia E or E2 numai E1 va fi evaluat ă dacă ea
este adev ărată. Acest tip de reprezentare este interesant deoarece expresia
booleană este o condi ție într-o instruc țiune iterativ ă sau condi țională; de
exemplu : 1
if E then S else S sau
while E do S sau
repeat S until E
Expresia urm ătoare conține un exemplu de expresie booleană
if A < B or A > D then A := A+1;
Ea se traduce prin cuadruple astfel :
( 0 ) if A < B goto ( 3 )
( 1 ) if A > D goto ( 3 )
( 2 ) goto ( 5 )
( 3 ) T1 := A+1
( 4 ) A :=T1 atributată
pentru expresii
booleene
Codul generat
Automate, limbaje și compilatoare
154 ( 5 ) ……
Dac ă utilizăm o analiz ă ascendent ă, când este generat un cuadruplu nu se
cunoaște încă intrarea în tabela cuadruplelor ce corespunde ie șirii adevărat; nu
putem, deci, completa acest cuadruplu. Codul generat pentru expresii booleene va
conține un num ăr de cuadruple de salt (condi țional și/sau necondi țional) care vor
rămne incomplete. Ele se vor completa în func ție de context. Cuadruplele
incomplete trebuie memorate într-o list ă. În realitate lucr ăm cu două liste asociate
unei expresii booleene: una pentru ie șirile adev ărate și una pentru cele false.
Fiecare list ă conține și cuadruple incomplete. Pentru a manipula aceste liste este
nevoie de urm ătoarele funcț ii:
– Crează_lista( n): c r e a ză o listă conținând cuadruplul incomplet cu indicele
în tabela cuadruplelor ; n
– Concateneaz ă_liste ( ) : concateneaz ă listele definite de pointerii și
, și returneaz ă un pointer spre noua list ă ; 2 1L , L 1L
2L
– Completeaz ă_lista ( ) : completeaz ă lista definit ă de pointerul n,L L cu
indicele al tabelei de cuadruple. n
Folosim atributele E.true și E.false care con țin pointerii catre listele asociate
ieșirilor “adevă rat” și respectiv “ fals” .
Consider ăm regula E → E1 or E2 și avem :
– dacă E1 este adev ărată atunci E este adev ărată fără a evalua E; deci
ieșirile adevărate ale lui E sunt acelea și cu cele ale lui E1 ; 2
– dacă E1 este fals ă atunci trebuie evaluat ă E; deci ieșirile false ale lui E1
corespund cu primul cuadruplu al lui E2; 2
– dacă E1 este falsă atunci ie șirile lui E corespund cu cele ale lui E2;
Acțiunile semantice vor fi:
– completarea listei E.false cu indicele primului cuadruplu al lui E2 d i n
tabloul cuadruplelor ; 1
– concatenarea listelor E1.true ș i E2.true pentru a crea lista E.true ;
– punerea în coresponden ță a ieșirilor false ale lui E2 cu cele ale lui E.
Pentru regula E → E1 and E2 avem :
– dacă E1 este fals ă atunci E este falsă fără a evalua E; deci ieșirile false
ale lui E sunt acelea și cu cele ale lui E1 ; 2
– dacă E1 este adev ărată atunci trebuie evaluat ă și expresia E2; ieș irile
adevărate ale lui E1 corespund primului cuadruplu al lui E2;
– dacă E1 este adev ărată, atunci ie șirile lui E corespund cu cele ale lui E2;
Automate, limbaje și compilatoare
155 Acțiunile semantice sunt :
– completarea listei E1.true cu indicele primului cuadruplu al lui E2;
– concatenarea listelor E1.false și E2.false pentru a crea lista E.false ;
– punerea în coresponden ță a ieș irilor adev ărate ale lui E2cu cele ale lui E .
Pentru regula E → not E1 este suficient s ă se inverseze ie șirile lui E1
pentru a ob ține pe cele ale lui E.
Pentru regula E → E1 o r E2, trebuie completat ă lista E1.false cu
indicele din tabloul cuad ruplelor unde apare pr imul cuadruplu al lui E2. Dar
această listă este cunoscut ă numai dup ă ce s-a utilizat aceast ă regulă de derivare.
Trebuie modificat ă regula astfel înct primul cuadruplu al lui E2 să poată fi
accesibil atunci când ac țiunea semantic ă are nevoie de el. Ad ăugam un simbol
neterminal M căruia îi ata șăm un atribut ce memoreaz ă primul cuadruplu care
urmează codului generat pentru E1. Acesta ne permite s ă completă m lista
E1.false când codul corespunz ător lui E2 a fost generat. Vom avea :
E → E1 or ME2 @1
M → ε @2
@1 . . . . . . . . . .
Completeaz ă_Lista ( E1.false , M.cuadruplu )
. . . . . . . . . .
@2 M.cuadruplu :=Cuadruplu_nou
Deci variabilei M îi asociem atributul M.cuadruplu care memoreaz ă
indicele primei intr ări libere din tabloul cuadruplelor; acesta este indicele
primului cuadruplu al lui E . Raționând ca mai sus, rezultă următoarea asociere
a acțiunilor semantice pentru regulile de mai jos : 2
E → E1 or ME2 @1
E → E1 and ME2 @2
E → not E1 @3
E → ( E1) @4
E → id @5
E → id1 oprel id2 @6
M → ε @7
Automate, limbaje și compilatoare
156 @1 E.true := Concateneaz ă_liste ( E1true, E2.true ) .
E.false := E2.false
Completeaz ă_lista (E1false , M.cuadruplu) .
@2 E.true := E2.true
E.false := Concateneaz ă_liste( E1.false , E2.false )
Completeaz ă_lista (E1.true , M.cuadruplu )
@3 E.true := E1.false
E.false := E1.true
@4 E.true := E1.true
E.false := E1.false
@5 E.true := Creaz ă_Lista ( Cuadruplu_nou )
E.false := Creaz ă_Lista ( Cuadruplu_nou+1 )
Gen_cuadr ( oprel , id.intrare , _ , _ )
Gen_cuadr ( goto , _ , _ , _ )
@6 E.true := Creaz ă_Lista ( Cuadruplu_nou )
E.false := Creaz ă_Lista ( Cuadruplu_nou+1 )
Gen_cuadr ( oprel , id1.intrare , id2.intrare , _ )
Gen_cuadr ( goto , _ , _ , _ )
@7 M.cuadruplu := Cuadruplu_nou
O nouă
gramatică
atributată
pentru expresii booleene
Automate, limbaje și compilatoare
157 )Teme Curs
Teste Autoevaluare
1. Aplicaț i algoritmul de adu cere la forma polonez ă pentru expresia
…………………………………………………………………………. 1 punct (b a c+ ∗
2. Genera ți codul de tip arbore pentru instruc țiunea
if id 1>id2 then id 2:=id1**2…………………………. 1 punct
3. Transpune ți în cod cu trei adrese instruc țiunea A<B or C
………………………………… ……………………………………………… 1 punct
4. Generara ți codul intermediar pentru expresia BA>, folosind algoritmul
care utilizeaz ă valorile fals și adevărat………………………………….. 1 punct
5. Aplica ți algoritmul de tip sc urt circuitare pentru a genera codul
corespunz ător expresiei A or not B and C ……………………………………… 5 puncte
Oficiu …………………………………………… ..…………………………. 1 punct
Automate, limbaje și compilatoare
158
Răspunsuri
1. ()() ε + ∗$, , b a c
()() c $, , b a +∗
( ) ( )c $, , b a∗ +
() c $, ( ), b a∗ +
( )ca $, ( ), b∗ +
( )ca $, ( ), b∗+
() cab $, ( ),∗ +
() + ∗cab $, ( ),
( )+ ∗ε cab $, ,
() ∗ + ε cab $, ,
2.
/•\ if
/ | \
/ | \
• > • := • goto
/ \ / \ \
/ \ / \ \
id1• id2• id2• • ** •et1
/ \
/ \
id1• • 2
3.
(0) if A<B goto (3)
(1) T1:=0
(2) goto (4) (3) T
1:=1
(4) T2:=T1 or C
4.
(0) if A>B goto (3)
(1) T1:=0
(2) goto (4)
(3) T1:=1
(4) …
5.
Automate, limbaje și compilatoare
159
Evaluăm expresia descrisă de arbore parcurgndu-l ascendent și executând
acțiunile semantice asociate fiec ărui nod. Presupunând c ă valoarea lui
Cuadruplu_nou este 100 , avem :
Nodul 1 : E.true := { 100 }
E.false := { 101 } ( 100 ) if A goto _
( 101 ) goto _
Se crează listele E.true și E.false, și două cuadruple incomplete la 100 și 101 .
Nodul 2
: M.cuadruplu := 102
Indicele 102 con ține primul cuadruplu al lui E , adică „not B and C“ 2
Nodul 3: E.true := { 102 }
E.false := { 103 } ( 102 ) if B goto _
( 103 ) goto _
Se creaz ă listele E.true și E.false, și două cuadruple incomplete la 102 și 103 .
Nodul 4
: E.true := { 103 }
E.false := { 102 } Se inverseaz ă listele corespunz ătoare ieșirilor adev ărat și fals, deoarece se
testează expresia „not B“.
Nodul 5
: M.cuadruplu := 104
Indicele 104 con ține primul cuadruplu al lui E , adică „C“. 2
Nodul 6 : E.true := { 104 }
E.false := { 105 } ( 104 ) if C goto _
Automate, limbaje și compilatoare
160 ( 105 ) goto _
Se creaz ă listele E.true și E.false și două cuadruple incomplete la 104 și 105.
Nodul 7: E.true := { 104 }
E.false := { 102 ,105 }
Se crează listele E.true și E.false și se completeaz ă cuadruplul de la (103) prin
valoarea M.cuadruplu, adic ă 104:
( 103 ) goto 104
Nodul 8 : E.true := { 100 , 104 }
E.false := { 102 , 105 }
Se crează listele E.true ș i E.false și se completeaz ă cuadruplele listei E.false,
adică cuadruplul cu indicele 101, prin valoarea M. cuadruplu =102
( 101 ) goto 102
Obținem la ie șire listele de cuadruple incomplete :
E.true := { 100 , 104 } E.false := { 102 , 105 }
și următoarea listă de cuadruple :
( 100 ) if A goto _ ( 101 ) goto 102
( 102 ) if B goto _
( 103 ) goto 104 ( 104 ) if C goto _
( 105 ) goto _
Rezumat: S-au prezentat trei forme de repr ezentare a codului intermediar și
un exemplu pentru expresii booleene.
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se va implementa codul intermediar sub una din formele alese pentru a continua
etapele urm ătoare ale construirii compilatorului
Automate, limbaje și compilatoare
161
Teme Laborator/Seminar
1. Scrieți un program care s ă implementeze codul intermediar sub form ă de
arbori sintactici sau cod cu trei adrese
Rezumat: se implementează codul intermediar sub o form ă la alegere
Automate, limbaje și compilatoare
162 Notații
Curs 11 Optimizarea codului
Descriere Generală
Se prezint ă trei metode de optimizare a codului: simple, locale și globale. Se
detaliază modul de lucru la nivelul fiec ăreia și se explic ă pe exemple
avantajele optimiz ării respective.
Obiective
Cunoașterea unor metode de îmbun ătățire a codului intermediar, cu privire la
timp de rulare și memorie ocupat ă
Cuprins
II.6.1. Optimiză ri simple
II.6.2. Optimiză ri globale
II.6.3. Optimiză ri locale
Conținut Curs
Optimizarea codului este o faz ă opțională și are ca scop rearanjarea codului
intermediar sau obiect în vederea ob ținerii unui program mai eficient. Eficien ța
se referă atât la memoria folosit ă la execuție dar, mai ales, la timpul execu ției.
Denumirea de optimizare este improprie, deoarece se pot ob ține programe mai
bune dar foarte rar sunt și optime. Iat ă câteva dintre posibilele surse ale
optimizării:
– un bun algoritm de programare
– o alocare inteligent ă a regiș trilor
– compatibilizarea codului cu structura ma șinii
– propagarea constantelor
– utilizarea identit ăților algebrice
– reducerea aritmetic ă a operatorilor
– eliminarea subexpresiilor comune
– reordonarea codului.
Dacă optimizările sunt structurate modul ar, ele nu vor duce la o cre ștere Curs 11
Durata :
2 ore
Generalit ăți
Automate, limbaje și compilatoare 163
substanțială a complexit ății programului. Îmbun ătățirea codului poate fi realizat ă
în paralel cu analiza semantic ă, în paralel cu generarea de cod sau într-un pas
separat. A șa cum am precizat, optimizarea se poate realiza atât asupra codului
intermediar cât și asupra codului obiect. În ultimul caz, îmbun ătățiri importante
ale eficien ței execuției se pot ob ține dacă în paralel cu ge nerarea de cod se
urmărește optimizarea aloc ării regiștrilor sau folosirea codului de instruc țiuni ale
mașinii. De aceea, metodele folosite pentru optimizarea codului obiect sunt
puternic dependente de ma șină și, deci, mai dificil de prezentat într-un mod
unitar. În cele ce urmeaz ă ne vom ocupa de optimizarea codului intermediar.
II.6.1. Optimiz ări simple
Una din cele mai simple optimiz ări este aplatizarea : ea constă în
înlocuirea expresiilor ce pot fi evaluate în timpul compil ării prin valorile lor. De
exemplu, expresia C A A + + + = 3 2 poate fi înlocuit ă prin C A A++=5 ,
unde înlocuieș te expresia . 5 3 2+
Pentru aplatizarea codului se poate ține seama de :
– unele identit ăți algebrice ; de exemplu
X X/XX XX XX XX X
= −== ∗= ∗= += +
00 01100
– proprietățile de asociativitate și comutativitate ale unor operatori; de exemplu,
expresia se poate înlocui cu 7 5+ + +B A BA++12 .
În strânsă legă tură cu identităț ile algebrice se afl ă și reducerea aritmetic ă a
operatorilor, care const ă în înlocuirea unui operator cu altul mai pu țin costisitor;
de exemplu
1. i i i i + = ∗ = ∗ 2 2
2. 5 0. 2 . x / x∗ =
O altă optimizare simpl ă este propagarea constantelor și constă în
înlocuirea variabilelor cu valorile lor, dac ă aceste valori sunt cunoscute la
compilare. De exemplu secven ța de program
0 180141592 3
. / PI : D. : PI
==
Aplatizarea
Propagarea constantelor
Automate, limbaje și compilatoare 164
poate fi rescrisă ca
0 . / . D:. PI:
180 141592 3141592 3
==
sau încă
0174644 0141592 3
. D:. PI:
==
II.6.2. Optimiz ări globale
Cea mai mare parte a timpului de op timizare a codului intermediar este
destinat optimiz ării buclelor. Pentru a determ ina diferitele bucle ale unui
program se utilizeaz ă graful de flux. El este un graf orientat ce define ște relațiile
dintre blocurile de baz ă. Un bloc de baz ă este format din instruc țiuni consecutive
ale programului, care alc ătuiesc o zon ă accesibil ă la execu ție doar prin
instrucțiunea de început și sunt executate una dup ă alta exact în ordinea în care
apar în program. Astfel, controlul execu ției părăsește blocul de baz ă prin ultima
instrucțiune din bloc. Doar într-un bloc de baz ă se pot controla variabilele f ără
perturbații exterioare; deci, împ ărțirea unui program în blocuri de baz ă este
absolut necesar ă. Două blocuri de baz ă dintr-un program nu pot avea instruc țiuni
comune; înseamn ă că împărțirea unui program în blocuri de baz ă este echivalent ă
cu partiționarea sa.
Având o secven ță de instruc țiuni (cu trei adrese) putem ob ține lista
blocurilor de baz ă în două etape:
a) se determin ă primele instrucț iuni ale blocurilor
b) pentru fiecare prim ă instrucțiune se construiește blocul ei.
Dac ă în urma acestor opera ții rămân instruc țiuni neincluse în vreun bloc
ele pot fi eliminate deoarece nu vor fi executate niciodat ă. Determinarea
primelor instruc țiuni se face astfel:
– prima instruc țiune din program este prima instruc țiune a unui bloc
– o instruc țiune ce urmeaz ă unei instruc țiuni de transfer este o prim ă instrucț iune
– o instruc țiune la care trimite o instruc țiune de transfer este o prim ă instrucț iune.
Blocul corespunz ător unei prime instruc țiuni conț ine aceast ă instrucțiune
precum și cele care urmeaz ă până la următoarea prim ă instrucțiune, exclusiv
aceasta.
Prezent ăm în continuare diferite tipuri de optimizare la ni velul unui bloc
de bază, luând ca exemplu algoritmul ce efectueaz ă produsul scalar a doi vectori:
Bloc de baz ă
Automate, limbaje și compilatoare 165
produs : = 0
indice : = 1
repeat
produs : = produs + A [indice] ∗ B[indice]
indice : = indice +1
until indice >20
Presupunând c ă unui cuvânt îi corespund patru octe ți, programului de mai sus îi
corespunde urm ătoarea secven ță de cuadruple:
(1) produs : = 0
(2) indice : = 1
(3) T1 : = 4 ∗ indice
(4) T2 : = adresa (A) – 4
(5) T3 : = T2[T1]
(6) T4 : = 4 ∗ indice
(7) T5 : = adresa (B) – 4
(8) T6 : = T5[T4]
(9) T7 : = T3 ∗ T6
(10) T8 : = produs +T7
(11) produs : = T8
(12) T9 : = indice +1
(13) indice : = T9
(14) if indice < = 20 goto (3)
(15) –
Graful de flux asociat este cel din figura 6.1.
O primă optimizare const ă în determinarea invarianț ilor din bucle și scoaterea
lor în afară. Un invariant este un calcul ce dă acela și rezultat la fiecare itera ție.
Prin scoaterea în afară a invarian ților aceștia se execută o singur ă dată înainte de
intrarea în bucl ă și deci num ărul cuadruplelor ce se execut ă se micșorează. În
blocul BL2 , cuadruplele
(4) T2 : = adresa (A) – 4 și
(7) T5 : = adresa (B) – 4
reprezintă invarian ți dacă spațiul de memorie rezervat vectorilor A și B este
alocat în mod static.
Automate, limbaje și compilatoare 166
Figura 6.1
Dacă scoatem din blocul 2BL cuadruplele (4) și (7) obținem graful de
flux din figura 6.2.a. Aceste cuadruple sunt plasate înaintea lui 2BL și formeaz ă
un bloc . 3BL
Eliminarea invarianților
Automate, limbaje și compilatoare 167
Figura 6.2
Blocurile 1BL și pot fi combinate într -un singur bloc deoarece, 3BL 1BL este
singurul predecesor al lui i a r 3BL 2BL este singurul succesor al lui 1BL
(figura 6.2.b )
Scoț ând cuadruplele (4) și (7), num ărul cuadruplelor din buclă scade de
la 12 la 10 iar num ărul de cuadruple executate scade de la 2+12*20 = 242 la
4+10*20 = 204. Codul obț inut poate fi optimizat în continuare prin eliminarea
unor variabile induse . Acestea sunt variabile ale c ăror valori formeaz ă pe
parcursul execu ției repetate a ciclului, o progresie aritmetic ă. În exemplul nostru,
variabila indice crește de la 1 la 20 cu pasul 1 iar 1T crește de la 4 la 80 cu pasul
4. Variabila care se elimin ă este, în general , cea care este utilizat ă pentru calculul
alteia. În cazul nostru se poate elimina variabila indice; cuadruplul
(3) T1: = 4*indice
se va înlocui cu
(3) T1: = T1+4
Variabila 1T nu are valori ini țiale ; de aceea trebuie ad ăugat un cuadruplu pentru
a o inițializa la valoarea 0, deoarece la prima itera ție ea are valo area 4. Acest
cuadruplu va fi inserat înaintea blocului BL2. Cuadruplele (2), (12) și (13) , care
utilizează variabila indice, se elimin ă. Cuadruplul (14) se modific ă pentru a
utiliza variabila 1T în locul variabilei indice. La ultima execu ție, 1T trebuie s ă
aibă valoarea 80, deci noul cuadruplu (14) este
(14) if T1< = 76 goto (3)
Eliminarea
variabilelor induse
Automate, limbaje și compilatoare 168
Astfel, la ultima itera ție 1T va avea valoarea 80. Se creaz ă un nou bloc
pentru a ini țializa variabilele 3BL
1T și 4T iar blocurile 1BL și se combin ă
într-unul singur, deoarece 3BL
1BL este singurul predecesor al lui BL3 iar BL3 este
singurul succesor al lui 1BL; astfel se obtine graful de flux cu variabilele induse
eliminate
II.6.3. Optimiz ări locale
Optimiz ările locale constă în eliminarea instruc țiunilor inutile, date de
existența a dou ă sau mai multe subexpresii comune, adic ă subexpresii
echivalente sau care produc acela și rezultat.
În cazul subexpresiilor comune este suficient s ă calculăm rezultatul o singur ă
dată și apoi doar s ă-l referim.
Exemplul 6.1. Fie secven ța de program
) x x )/( x/y ( z y) x/y ( x x y) x ( ) ( x
∗ = =+ ∗ =− ∗ + = 20 1
Codul intermediar generat este:
(1) T1 : = (1+20)
(2) T2 : = -x
(3) x : = T1*T2
(4) T3 : = x∗x
(5) T4 : = x/y
(6) y : = T3+T4
(7) T5 : = x/y
(8) T6 : = x∗x
(9) z : = T5/T6
(10) y : = z
Expresia xx∗ se calculeaz ă de două ori, în instruc țiunile (4) și (8); vom
elimina a doua opera ție de calculare a acestei valori. În liniile (5) și (7) avem
aceeași operație, y x. Valoarea lui x rămâne neschimbată, dar a lui y se
modifică în linia 6 ș i deci y x nu este subexpresie comun ă.
Pentru a elimina instruc țiunile inutile se utilizeaz ă o structur ă de date
particular ă în vederea analiz ării unui bloc de baz ă: graful orientat f ără cicluri
Automate, limbaje și compilatoare 169
(GOFC ). El descrie modul cum valoarea calculat ă pentru fiecare cuadruplu este
utilizată în alte instruc țiuni ale blocului. El perm ite detectarea subexpresiilor
comune unui bloc, a iden tificatorilor utiliza ți într-un bloc și evalua ți în altul și a
cuadruplelor ale c ăror valori sunt utilizate în afara blocului. Într-un ,
nodurile sunt etichetate astfel: GOFC
– fiecare terminal este etichetat cu un identificator (nume de variabil ă sau de
constantă) indiciat prin valoar ea 0; indicele precizeaz ă că este vorba de o valoare
inițială a identificatorului;
– un nod interior este etichetat pr intr-un operator; el reprezint ă valoarea calculat ă
pentru expresia corespunzătoare acestui nod;
– nodurile interioare pot fi etic hetate, în plus, printr-o mulț ime de identificatori
care au valoarea calculat ă în acel nod.
Nu trebuie confundat gr aful de flux cu un . Fiecare nod al unui
graf de flux poate fi reprezentat printr-un GOFC . Pentru a construi un ,
se ia fiecare bloc de baz ă și se trateaz ă toate cuadruplele. Când se întâlne ște un
cuadruplu de tipul , se examineaz ă nodurile reprezentând valorile
curente ale identificatorilor GOFC
GOFC
C op B : A=
B și . Se creaz ă un nou nod etichetat op cu doi
fii, la stânga nodul asociat lui C
B și la dreapta cel asociat lui C. Apoi se adaug ă
eticheta nodului op. Dacă există deja un nod reprezentând pe , nu se
mai creaz ă un nou nod, doar se adaug ă la lista identificatorilor asocia ți acestui
nod. Dacă a etichetat în prea labil un alt nod, care nu e terminal, se elimin ă
această etichet ă, căci valoarea curentă a lui este valoarea noului nod creat.
Pentru cuadruplul A CopB
A
A
A
B : A= nu se crează un nou nod, ci se adaugă eticheta A la
nodul ce corespunde valorii curente B. Pentru a defini func ția de creare a unui
, ce returneaz ă un pointer c ătre ultimul nod creat, utiliz ăm următoarele
funcții : GOFC
– : returneaz ă un pointer c ătre nodul cu eticheta identificator
dacă exist ă , în caz contrar returneaz ă ) tor identifica ( Nod
Nil;
– (op, pointer_st, pointer_dr) : returneaz ă un pointer c ătre nodul
cu eticheta op care are ca descendent stâng nodul definit de pointer_st iar ca
descendent drept nodul definit de pointer_dr ; în caz contrar returneaz ă Nil; operator _ Nod
Vom aplica această funcț ie pentru blocul 2BL din figura 6.1;
Graf orientat fără cicluri
Automate, limbaje și compilatoare 170
Se observă c ă :
– subexpresiile comune apar în acela și nod; T1 și T4, de exemplu
– variabilele temporare inutile de tipul
T8 : = produs +T7
produs : = T8
apar în acela și nod.
GOFC permite reconstruirea listei simplificate a cuadruplelor eliminând
subexpresiile comune și cuadruplele de tipul B : A= cu excep ția celor care sunt
necesare. În cazul când lista asociat ă unui nod operator con ține numai variabile
temporare se alege una la întâmplare, fiind foarte probabil ca ele s ă fie utilizate
numai în blocul de baz ă curent. De exemplu, în cazul nodului 4 1T , T∗ se poate
reține oricare din variabilele 1T și 4T. Dacă lista con ține și o variabil ă d i n
program, de exemplu , ar trebui s ă optăm pentru deoarece este
posibil ca aceasta s ă fie folosit ă în blocurile urm ătoare. Pentru a ști care variabil ă
este utilizat ă în blocurile urm ătoare, trebuie f ăcută o analiz ă globală, pe graful de
flux, a transferului de valori al e variabilelor între blocuri. Dac ă în urma acestei
analize rezult ă că, din lista de identificatori asociat ă unui nod, este posibil s ă
avem nevoie în blocurile urm ătoare de mai multe variabil e, atunci alegem dintre
acești identificatori unul la întâmplare, fie el A, 4T T,1 A
A, și pentru ceilal ți, fie ei
, introducem atribuirile kB ,… B , B2 1 A : B B , A Bk …., , A : : = ==2 1 .
Automate, limbaje și compilatoare 171
Teme Curs
Teste Autoevaluare
1. Ilustrați grafic (prin arbori sintactici) efectul aplatiz ării expresiei
() 3 2* i *………………………………………………………………………….. 1 punct
2. Generați codul intermediar cu trei adrese corespunzător programului de
mai jos, apoi realiza ți împărțirea în bloc uri de baz ă și construi ți graful de
flux.
FACT ← 1
for i = 2 to n do
FACT ← FACT ∗ i
FACTORIAL ← FACT
……………………………………………………………….. 4 (=2+1+1) puncte
3. Efectuați optimizări simple și locale pentru urm ătoarea secven ță de cod
intermediar
(1) T1 : = (1+20)
(2) T2 : = -x
(3) x : = T1*T2
(4) T3 : = x∗x
(5) T4 : = x/y
(6) y : = T3+T4
(7) T5 : = x/y
(8) T6 : = x∗x
(9) z : = T5/T6
(10) y : = z
………………………………………………………………….. 2 puncte
4. Care este deosebirea dintre graful de flux si
GOFC?………………………………………………………………………………………… 1 punct
5. Ce se reduce prin optimiz ările globale (memorie,
timp)?………………………………………………………………………………….. 1 punct
Oficiu………………………………………………………..………… 1 punct
Automate, limbaje și compilatoare 172
Răspunsuri
1.
2.
Codul intermediar
(1) FACT ← 1
(2) i ← 2
(3) if i>n then goto (7)
(4) FACT ← FACT * i
(5) i ← i+1
(6) goto (3) (7) FACTORIAL ← FACT
Împărțirea în blocuri de baz ă
Graful de flux
Automate, limbaje și compilatoare 173
Figura 6.3
3. D u pă propagarea constantelor și eliminarea expresiilor comune, codul
devine:
T2 : = – x
x : = 21*T2
T3 : = x∗x
T4 : = x/y
y : = T3+T4
T5 : = x/y
z : = T5/T3
y : = z
4. Fiecare nod al unui graf de flux poa te fi reprezentat printr-un GOFC
5. Memorie și timp
Rezumat: S-au prezentat modalit ăți de realizare a optimiz ărilor de tip: local,
global, simplu
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Pentru fiecare tip de optimizare studiat se cere s ă se scrie câte un program care s ă
implementeze metoda respectiv ă.
Automate, limbaje și compilatoare 174
Teme Laborator/Seminar
1. Scrieți un program care s ă realizeze împ ărțirea în blocuri de baz ă.
2. Scrieți un program care, pentru o secven ță de cod intermediar cu trei
adrese, să efectueze optimizările simple și locale
3. Scrieți un program care efectueaz ă optimizări globale la nivelul unui bloc
de bază
Rezumat: se implementeaz ă tipurile de optimiz ări studiate
Automate, limbaje și compilatoare 175
Notații
Automate, limbaje și compilatoare 176
Curs 12 Generarea codului obiect
Descriere Generală
Se prezint ă trei forme de reprezentare a codului intermediar: forma polonez ă,
arbori sintactici ș i triplete. Ca model se prezint ă codul intermediar pentru
expresii booleene
Obiective
– cunoașterea tipurilor de cod obiect
– cunoașterea generă rii codului pentru calculato are cu un singur registru
– cunoașterea metodelor de generare a codul ui pentru calcul atoare cu regi ștri
generali
– modalități de îmbun ătățire a codului obiect
Cuprins
II.7.1. Generalit ăți
II.7.2. Generarea codului pentru cal culatoare cu registru acumulator
II. 7.3. Generarea codului pentru calculatoare cu regi ștri generali
II.7.3.1. Gestiunea regi ștrilor
II.7.3.2. Utilizarea GOFC în generarea codului obiect
Conținut Curs
II.7.1. Generalit ăți
Ultima faz ă a compil ării are ca scop sinteza programului obiect, program
executabil sau aproape executabil, în sensul c ă el poate fi preluat de un alt
procesor de limbaj implementat pe calculatorul țintă și tradus de acesta în cod
executabil. Generarea codului este una din fazele cele mai importante și mai
dificile. Pentru implementarea sa sunt necesare cuno ștințe aprofundate despre
mașina cu care se lucreaz ă.
Forma luat ă de programul obiect este, de obicei, una din urm ătoarele:
1) Program executabil : rezultatul ob ținut este direct executabil. El este stocat
într-o zon ă de memorie fix ă și toate adresele sunt puse la zi. Aceast ă formă este Curs 12
Durata :
2 ore
Automate, limbaje și compilatoare 177
recomandat ă pentru programele mici. Inconvenientul s ău constă în lipsa de
flexibilitate. Compilarea modular ă este imposibil ă, toate modulele trebuind s ă fie
compilate simultan.
2) Program obiect . Aceast ă formă este numită și translatabil ă; înainte de
execuție este necesară faza de editare de leg ături, care permite și legarea unor
rutine din bibliotecă sau realizate de utilizatori. Este solu ția cea mai des întâlnit ă
în cazul compilatoarelor comerciale. 3) Program în limbaj de asamblare. Este forma cea mai simpl ă de generat,
deoarece instruc țiunile sunt foarte apropiate de ce le cu trei adrese. Programul este
reprezentat de o mulț ime de instruc țiuni simbolice care necesit ă o fază de
asamblare înainte de execu ție. Deci, generarea codului este simplificat ă, dar
rezultatul nu poate fi direct utilizabil.
4) Program într-un alt limbaj , care simplific ă mult generarea de cod, dar
necesită cel puțin o compilare suplimentar ă pentru a putea fi executat. Este cazul
preprocesoarelor de limbaje.
Generarea codului este dependent ă de calculatorul țintă ca și de sistemul
de operare al acestuia. De aceea prezentarea sa necesit ă unele presupuneri privind
structura calculatorului țintă și a setului s ău de instruc țiuni. Pe de alt ă parte, ea
este influen țată de forma codului intermediar precum și de gradul în care
compilatorul a rezolvat problemele traducerii: a f ăcut verific ările semantice, a
introdus conversii, a optimizat codul interm ediar, l-a structurat pe blocuri de
bază, etc. în cele ce urmeaz ă vom analiza generarea de cod pentru dou ă tipuri de
calculatoare:
a) calculatoare cu acumulator
b) calculatoare cu un num ăr de regi ștri generali.
Presupunem c ă în fazele anterioare s-au realizat toate verific ările
semantice, s-a optimizat codul intermediar, etc. Pentru fiecare variabil ă știm
adresa ei la execu ție, prin perechea (registru ce con ține o adresă de început a
înregistrării de activare, de plasamentul în aceast ă zonă). Mai presupunem c ă
toate opera țiile din codul intermed iar au un corespondent în setul de instruc țiuni
ale calculatorului iar variabilele sunt simple. Pentru uș urința înțelegerii vom
genera codul obiect în limbaj de asamblare în care variabilele apar prin numele
lor și nu prin referin țe, deplasamente, etc. Genera rea codului obiect apare ca un
proces în care se parcurge instruc țiune cu instruc țiune forma intermediar ă,
apelându-se pentru fiecare tip de instruc țiune proceduri de generare
Tipuri de cod
obiect
Automate, limbaje și compilatoare 178
corespunz ătoare.
Pentru a genera un cod eficient trebuie s ă se ț ină seama de unele detalii
legate de calculatorul țintă:
1) majoritatea calculatoare lor permit efectuarea unor ca lcule în mai multe feluri
utilizând diferite instruc țiuni; de exemplu 1+=nr : nr se poate traduce prin
MOV AX , nr ; încarc ă valoarea lui nr în registrul AX
INC AX ; incrementeaz ă 1 la conț inutul registrului AX
MOV nr, AX ; se stocheaz ă conținutul registrului AX în loca ția
corespunz ătoare lui nr
sau
ADD nr, 1 ; se adun ă 1 la con ținutul zonei de memorie nr
2) diferitele forme de traducere a aceleia și secvenț e de instruc țiuni nu folosesc,
în general , acela și număr de regiș tri.
Costul unei instruc țiuni const ă în lungimea sa în bi ți sau în timpul de
execuție. Strategiile optimiz ării tind s ă se concentreze pe reducerea costului de
execuție, deoarece majoritatea utilizatorilor apreciaz ă mai mult viteza de execu ție
decât spaț iul ocupat. Instruc țiunile care lucreaz ă cu regiștri, f ără a face apel la
memorie, au un timp de execu ție mai mic și ocupă mai puțină memorie. O alt ă
posibilitate de a optimiza codul const ă în eliberarea zonelor de memorie ocupate
de variabile nefolositoare. În momentul când o variabil ă devine nefolositoare și
valoarea sa se afl ă într-un registru, ea poate fi ștearsă din acesta. Când se ajunge
la finalul unui bloc de baz ă, valoarea fiec ărei variabile folositoare trebuie p ăstrată
fie într-un registru, fi e în memoria principal ă prin intermediul variabilelor
temporare.
II.7.2. Generarea codului pentru calculatoare cu registru
acumulator
Toate calculele trebuie efectuate într-un singur registru, numit adesea
acumulator. Acumulatorul va fi continuu aloc at la diferite variabile astfel încât s ă
se minimizeze num ărul de instruc țiuni ale codului generat. S ă luăm mai întâi un
exemplu simplu care arat ă cum poate fi utilizat în mod eficient registrul
acumulator. Printre instruc țiunile existente în limbajul de asamblare sunt
următoarele:
LOD X ; încarc ă valoarea X în registrul acumulator
STO X ; memoreaz ă conținutul registrului ac umulator într-un
Generalit ăți
Automate, limbaje și compilatoare 179
cuvânt de memorie notat cu X
ADD X ; adun ă valoarea lui X la valoarea acumulatorului
SUB X ; valoarea variabilei X se scade din valoarea acumulatorului MUL X ; valoarea variabilei X este multiplicată prin valoarea
acumulatorului DIV X ; valoarea acumulatorului se împarte la valoarea variabilei X
Toate cele patru operaț ii aritmetice plaseaz ă rezultatul în acumulator și lasă
neschimbat con ținutul lui X. Compilatorul utilizeaz ă forma polonez ă pentru
reprezentarea codului intermediar. Codul pentru opera torii aritmetici binari este
generat conform urm ătorului algoritm :
1) se încarc ă primul operand în acumulator;
2 ) s e a p l i c ă operatorul folosind al doilea operand și lăsând rezultatul în
acumulator;
3) se memoreaz ă rezultatul într-o variabil ă temporar ă.
De exemplu, expresia x+y, care se reprezint ă în forma polonez ă ca xy+, se
translateaz ă conform acestui algoritm în
LOD x ADD y
STO T1
unde T1 este adresa unei loca ții de memorie care con ține valoarea unui rezultat
intermediar. Codul pentru operatorul de asignare ,,: ='' este generat conform
următorului algoritm simplu :
1. se încarc ă valoarea p ărții drepte a instruc țiunii de asignare în acumulator;
2. se memoreaz ă acest rezultat în variabila specificat ă.
Algoritmul parcurge liniar șirul, aflat în form ă poloneză. Când este
întâlnit un operator, se selecteaz ă ultimele dou ă simboluri din stiv ă, se execut ă
operația indicată de operator, iar rezultatul ob ținut este plasat în stiv ă. Deoarece
operatorii sunt binari, se afi șază un mesaj de eroare dac ă stiva nu con ține doi
operanzi la întâlnirea unui operator. Dac ă algoritmul s-a terminat și au mai r ămas
operanzi în stiv ă, expresia nu este o instruc țiune de atribuire valid ă.
Consider ăm instruc țiunea
()D C * B A X++← care se reprezint ă în
forma polonez ă postfixă ca ←++D* XABC
Algoritmul precedent produce urm ătorul cod :
LOD B
MUL C
STO T1
LOD T1 Instruțtiuni
cod obiect
Automate, limbaje și compilatoare 180
ADD D
STO T2
LOD A
ADD T2
STO T3
LOD T3
STO X
Codul generat nu este optim , c ăci secven țe de tipul
STO Ti LOD Ti
sunt inutile. De asemenea, codul poate fi rearanjat folosind proprietatea de
comutativitate a operatorilor de adunare și înmulțire. Astfel, secven ța :
STO T2
LOD A
ADD T2
poate fi rescris ă sub forma
STO T2 LOD T2
ADD A
deoarece T2 + A are aceea și valoare cu A +T2.
II. 7.3. Generarea codulu i pentru calculatoare cu regi ștri
generali
II.7.3.1. Gestiunea regi ștrilor
În vederea gener ării codului obiect pentru calculatoare cu regi ștri generali
vom considera codul intermediar sub forma instruc țiunilor cu trei adrese. Pentru
ușurința exprimării vom lucra cu expresii aritme tice pentru care sunt verificate
condițiile de mai jos.
a) Variabilele sunt simple și alocate static. în vederea aloc ării regiștrilor trebuie
cunoscută starea lor: un registru poate fi disponibil, adic ă memoreaz ă o valoare
nesemnificativ ă, sau poate fi ocupat, când con ține o valoare utilizabil ă în
continuare. Not ăm cu mulțimea variabilelor a c ăror valoare se afl ă în
registrul ) R ( Var
R.
b) Pentru fiecare variabil ă este necesar s ă se cunoască locul unde se afl ă valoarea
sa curentă. Notăm cu mulțimea locurilor în care se afl ă la un moment ) X ( LocExemplu de
generare cod
obiect
Automate, limbaje și compilatoare 181
dat valoarea variabilei X.
c) Pentru utilizarea eficient ă a regiștrilor este necesar ă cunoașterea, pentru
fiecare apari ție a unei variabile în c odul intermediar, a urm ătoarei ei utiliz ări.
Procedura de determinare a urm ătoarei utiliz ări poate fi simplificat ă dacă ne
limităm la un bloc de baz ă și consider ăm că la ieșirea dintr-un bloc toate
variabilele sunt utilizate în continuare. Not ăm cu numărul următoarei
instrucțiuni din bloc ce folose ște valoarea curent ă a variabilei . Dacă
, înseamn ă că ) A ( Ni
A
0=) A ( Ni A nu are o utilizare urm ătoare în blocul curent.
d) Gestiunea regiștrilor generali este asigurat ă de procedura GESTREG care
întoarce o loca ție L ce urmeaz ă să fie folosit ă pentru memorarea unei valori a
unei variabile A obținută prin instruc țiunea C op B : A= . Locaț ia poate fi un
registru sau o loca ție de memorie. Procedura determin ă locația cercetând
succesiv urm ătoarele cazuri : L
1)B se află într-un registru R și este ultima ei utilizare înaintea unei atribuiri B:
= ….
Vom folosi pentru A chiar registrul folosit de B; deci R L← ;
2) există un registru R disponibil ; se ia RL=;
3) variabila este utilizat ă în continuare în blocul curent și se găsește un
registru care poate fi eliberat (este posibil ca to ți regiștri să fie ocupaA
ți); fie
acesta R. Se elibereaz ă registrul R prin salvarea valorii sale într-o loca ție de
memorie și se ia RL=.
4) trebuie folosit ă chiar loca ția de memorie rezervat ă pentru . A
Algoritmul de generare a codului este urm ătorul
Algoritmul 7.1 – ( ) 1 GENCOD
Intrare : O instruc țiune cu trei adrese de tipul C op B : A=
Ieșire : Codul obiect corespunz ător acestei instruc țiuni
Metoda :
1. Cheam ă funcția pentru a determina loca ția unde se va executa
operația ; în mod obișnuit GESTREG L
C op B L este un regist ru, dar poate fi și o locație de
memorie.
2. Consult ă mulțimea pentru a determina loca ția curentă ) B ( Loc 'B a lui B.
Preferăm un registru pentru 'B dacă valoarea lui B se află atât în memorie cât și
într-un registru. Dac ă valoarea lui B nu se afl ă deja în , genereaz ă
instrucțiunea : L
Informații
necesare la
generarea
codului
obiect
Algoritm de generare cod
obiect,
folosind procedura
GESTREG
Automate, limbaje și compilatoare 182
MOV B' , L
3. Genereaz ă instrucț iunea unde este loca ția curentă a lui C. Din
nou prefer ăm un registru dac ă valoarea lui C se află și în memorie și într-unul
sau mai mul ți regiștri. L , ' C op ' C
II.7.3.2. Utilizarea GOFC în generarea codului obiect
a ) Reordonarea nodurilor.
Avantajul utiliz ării grafurilor orientate f ără cicluri în generarea codului
obiect const ă în posibilitatea alegerii unei secven țe de instruc țiuni cu trei adrese
într-o ordine mai convenabil ă pentru obț inerea unui cod efic ient: program mai
scurt și variabile temporare mai pu ține.
Exemplul 7.1. Fie expresia ()()( )D C E B A+−−+ . în figura 7.1.a este
prezentat codul intermediar, în 7.1.b GOFC corespunz ător iar în 7.1.c codul
generat conform algoritmului anterior, considerând c ă avem disponibili doi
regiștri.
Să rearanjăm codul intermediar astfel încât T1 să apar ă imediat înaintea lui T4
T 2 : = C+D
T 3 : = E – T2
T 1 : = A+B
T 4 : = T1 – T3
Folosind din nou algoritmul obținem 1 GENCOD
MOV C, R0 ADD D, R0
MOV E, R1
SUB R0, R1
Optimizarea codului prin rearanjarea
nodurilor
Automate, limbaje și compilatoare 183
MOV A, R0
ADD B , R0
SUB R1, R0
MOV R0, T4.
Din exemplul anterior rezult ă că îmbunătățirea codului generat s-a
obținut prin plasarea instruc țiunii de calcul a lui 1 T imediat înaintea instruc țiunii
de calcul a lui 4 T, în cadrul c ăreia 1 T este primul operand. Pe baza acestei
observații putem irma c ă, de regul ăbținem un cod mai bun dac ă plasăm
calculul celui mai din stânga operand chiar înaintea instruc țiunii care con ține
operația. Astfel operandul se va g ăsi într-un registru în momentul când avem
nevoie de el, economisind astfel o memorare și o încărcare în registru. Pentru a
obține lista nodurilor din GOFC ordonate conform acestei observa ții, se parcurge
arborele de la r ădăcină spre frunze listând întâi nodurile rezultat. Apoi, listăm
nodurile operanzi începând cu cel mai din stânga dac ă toți părinții lui au fost
evaluați. Ne intereseaz ă numai nodurile interioare, c ărora le corespund
temporare. Se ob ține secven ța optimizat ă a instruc țiunilor în ordinea invers ă.
af , o
Algoritmul 7.2 – de listare a nodurilor (LISTNOD )
Intrare
imizată a instruc țiunilor în ordine invers ă : un GOFC
Ieșire : secven ța opt
Metoda :
while mai există noduri interioare nelistate do
begin
selecteaz ă un nod interior nelistat , ai cărui părinți au fost lista ți n
listeaz ă n
while c l me ai din stânga descendent al lui are toți părinții m n
lista ți și m nu este nod frunz ă do
begin
listeaz ă
d m
n ← m
en
end
b) Etichetarea nodurilor
i rezultatelor par țiale, păstrând pe cât posibil aceste Evitarea memor ări
Algoritmul de optimizare prin
rearanjarea
nodurilor
Automate, limbaje și compilatoare 184
valori în regi ștri mașinii, necesit ă cunoașterea num ărului de regi ștri necesari
generării codului pentru diferite secven țe de instruc țiuni cu trei adrese. Stabilirea
acestui num ăr se numeș te etichetare. Etichetarea se realizează vizitând nodurile
de jos în sus astfel încât un nod nu es te vizitat atâta timp cât descenden ții săi nu
au fost eticheta ți. Etichetarea nodurilor se face conform algoritmului urm ător:
Algoritmul 7.3 – de etichetare
Intrare enții săi etichetaț i : nodul n împreună cu descend
Ieșire : eticheta lui n
Metoda :
if n este nod terminal
then if n este descendentul cel mai din stânga al p ărintelui său
e th n
eticheta ( ) ← 1 n
else
eticheta ( n) ← 0
else
begin
fie kn ,…, n , n2 1 descendenț ii lui în ordinea dat ă de etichete :
cheta(
tan
eti eticheta(2n)≥…..≥eticheta(kn) 1n)≥
eticheta( n)max(etiche ( ) 1
k i≤ ≤←
1in−+i)
end
În cazul când este un nod binar cu descenden ții având etichetele
dată etichetat arborele, se poate genera codul folosind procedura
Algoritmul 7.4 – GENCOD2
Intrare t n
2 1n și n , formula de etichetare a sa devine
⎩⎨⎧
= +≠=2 1 12 1 2 1
1 n n dacă nn n dacă ) n , n max() n ( eticheta
O 2 GENCOD
pe care o prezentăm în continuare pentru cazul arbor ilor binari; extinderea sa la
arbori cu mai mult de doi descenden ți se poate face f ără dificultate.
: un arbore de derivare eticheta
Ieșire : codul obiect asociat arborelui
Determinarea
numărului de
regiștri
necesari
Automate, limbaje și compilatoare 185
Metoda : Algoritmul este o procedură recursiv ă care aplicată unui nod
care reține toți regiștri disponibili la un moment dat, din cei generează codul arborelui dominat de acel nod .
Se utilizeaz ă :
a) o stivă Stiva r
ai mașinii; i stiva con ține toți cei nițial r regiștri. Pentru a lucra cu o stiv ă s s
folosesc :
• procedure
a care depune în stiva valoarea ) x , s ( PUSH s x
• funcț ia POP escarcă stiva s ) s ( care d
a a din vârful stivei
a ivei.
care con ține
s variabilelor temporare , pe care le • funcț ia ) care întoarce valo res ( VARF
• procedur ) s ( care permut ă două valori din vârful st PERM
La ieșirea din ) n ( D2 , registrul din vârful stivei este cel GENCO
tă pentru nodul valoarea calcula n.
b) o stivă Temp care men ține li ta L, T , T10
poate folosi în continuare. Când cei r regiștri sunt ocupa ți, l ia o celul ă
temporară din vârful stivei.
algoritmu
procedure GENCOD2 (n) begin
if n este un nod frunz ă reprezentând operandul nume
s și e te cel mai din stânga descendent al tat ălui său
then
{ cazul 1 }
write (' MOV ' , nume, VÂRF (Stiva ) )
else if n este un nod interior cu operatorul op ,
descendentul stâng 1n și cel drept 2n
then
{ cazul 2 }
if eticheta (2n) = 0
then
begin
fie nume operandul reprezentat de 2n
call GENCOD2 (1n)
write (op, nume, ÂR V F (Stiva ))
end
else if 1eticheta )<eticheta ) și ≤ (1n (2n
Algoritm recursiv de generare cod
Automate, limbaje și compilatoare 186
eticheta(1)<nr
then
{ cazul 3 }
begin
call PERM ( Stiva )
call GENCOD2 (2n)
reg ← POP ( Stiva )
call GENCOD2 (1n)
write (op, reg, VÂ F( R Stiva) )
call PUSH (Stiva, reg )
call PERM (Stiva )
end
else if ) eticheta(n ) eticheta(n 11 2≤ ≤ ș i
etich r ) n ( eta<2
then
ul 4 } { caz
begin
call GENCOD2 ( n1)
reg ← POP ( Stiva )
call GENCOD2 ( n2)
write (op, VÂRF( tiv S a ), reg)
call PUSH (Stiva, reg )
end
else
{ cazul 5: ambele etichete sunt mai mari decât n }
begin
call GENCOD2 ( )
2n
t ← POP ( Temp)
write ('MOV ' , VÂRF(Stiva), t )
call GENCOD2 (1n)
call PUSH (Temp, t )
write ( op, t, VÂRF (Stiva ) )
end
end
Automate, limbaje și compilatoare 187
În funcț ie de nodul întâlnit, al goritmul se poate af la în una din situa țiile
ză, fiind cel mai din stânga descendent al nodurilor tat ă. El are
2) Nod interior, având ca descendent dreapta un nod frunz ă. Operația indicată de
inte r, având ca operanzi subarborii domina ți de nodurile și următoare :
1) Nod frun
eticheta 1, deci necesit ă o încărcare într-un registru a valorii reprezentate de
acest nod. Extragem registrul din vârful stivei Stiva și executăm instruc țiunea
MOV de încărcare în el a operandului indicat de nod.
nodul curent poa te fi realizat ă cu condiția evaluării în prealabil a descendentului
stâng. Se apeleaz ă recursiv algoritmul 2 GENCOD pentru descendentul stâng,
după care se genereaz ă codul opera ției nodului curent folosind registrul din vârful
stivei Stiva .
3) Nod rio1n2n
cu ) eticheta(n ) eticheta(n2 1< și r ) eticheta(n 1<. Procedura se apelea
recurs pera oi al primului. Inversarea
ordinei de genera re este precedată de permutarea a doi regiștri din vârful stivei
Stiva ; este vorba de acei regi ștri ce vor con ține rezultatele opera nzilor. înainte de
a din procedur ă, stiva se reface repermutând regi ștri din vârful s ău.
4) Nod interior în condi țiile de la 3), doar c ă ) eticheta(n ) eticheta(n2 1≥ ză
iv pentru a genera codul o ndului doi și ap
ieșire
si
permutarea și ref
odurile și cu
și la
r ) eticheta(n 2<. Se execut ă operațiile de voie de
acerea celor doi regi ștri din vârful stivei.
5) Nod interior, având operanzii subarbori domina ți de n la 3) f ără a mai fi ne
1n 2n
{}2 1, i , r ) n ( etichetai∈ ≥ . După generarea codului pentru al doilea operand se
strulu i din vârful stivei (cel ce conț ine rezultatul
operandului) într-o variabilă temporară extras ă din stiva Temp . După generarea
codului pentru primul operand, variabila este reîntoars ă î p, iar codul de
operație generat va con ține referin țe la variabila temporară registrul din
vârful stivei. salvează con ținutul regi
n Tem
Automate, limbaje și compilatoare 188
Teme Curs
aluare
dul corespunz ător expresiei
Teste Autoev
1. Optimizați co ←++D * XABC , în cazul când
se folosește un singur registru…………………………………….. 1 punct
ă se genereze codul obiect folosind algoritmul
GENCOD1……………………………………………..……….. 2 puncte
3.
e arborele urm ător
2. Fiind dat codul cu trei adrese
2 C
2 3 42 1 31
T T : TT T : TB A : T
+ =+ =− =
A : T− =
s
Folosind algoritmul de li stare a nodurilor, rearanja ți codul intermediar dat
d
…………………………………………………………………… 2 puncte
4.
)……………………………………….….. 4 puncte
Oficiu……………
Folosind algoritmul GENCOD2, genera ți codul corespunz ător expresiei
() (() D C E B A+ − − +
……………………………………………..……. 1 punct
Automate, limbaje și compilatoare 189
Răspunsuri
1.
B
C
2.
R0
SUB B, R0
T7 : = D+E
T6 : = A+B
3
4.
GENCOD2 (T4) [R1 R0]
GENCOD2 (T3) [R0 R1]
)
]
C) [R0] LOD
MUL
ADD D
ADD A
STO X
MOV A,
MOV A, R1
SUB C, R1
ADD R1, R0
ADD R1, R0
MOV R0, D
3.
T5 : = T6 – C
T4 : = T5 ∗ T8
T3 : = T4 – E
T2 : = T6 + T4
T1 : = T2 ∗ T
GENCOD2 (E [R0 R1]
MOV E, R1
GENCOD2 (T2) [R0
GENCOD2 (
MOV C, R0
ADD D, R0
SUB R0, R1
Automate, limbaje și compilatoare 190
GENCOD2 (T1) [R0]
) [R0]
GENCOD2 (A
MOV A, R0
ADD B, R0
SUB R1, R0
Rezumat: S-au prezentat doi algoritmi de generare a codului obiect și câte un
algoritm de optimizare di n punct de vedere al num ărului de instruc țiuni și al
numărului de regi ștri.
Lucrari Practice (Laborator/Seminar)
de optimizar e a codului folosind graful orientat f ără
icluri și un algoritm de genera re a codului obiect
ul de listare a nodurilor
2. Implementa ți algoritmul de etichetare a nodurilor
Conținut Laborator/Seminar
Se vor implementa algoritmii
c
Teme Laborator/Seminar
1. Implementa ți algoritm
3. Implementa ți algoritmul GENCOD2
Rezumat: se implementeaz ă un algoritm de generare cod obiect și algoritmii
de optimizare
Automate, limbaje și compilatoare 191
Automate, limbaje și compilatoare 192Notații
Curs 13 Tabela de simboluri
Descriere Generală
Se prezint ă noțiuni generale cu privire la importan ța tabelei de simboluri,
diferite moduri de implementare și gestiune a tabelei de simboluri și
reprezentarea identificatorilor ținând seama de domeniul de valabilitate.
Obiective
– cunoa șterea structurii și utilității tabelei de simboluri
– cunoa șterea principalelor moduri de organizare a tabelei de simboluri
Cuprins
II.8.1. Generalit ăți
II.8.2. Organizarea tabelei de simboluri
II.8.2.1. Tabele neordonate
II.8.2.2. Tabele ordonate alfabetic
II.8.2.3. Tabele arborescente
II. 8.2.4. Tabele dispersate
II.8.3. Reprezentarea identificatorilor ținând seama de domeniul de
valabilitate
Conținut Curs
II.8.1. Generalit ăți
Informa ția selectat ă de compilator în leg ătură cu numele simbolice care
apar în programul surs ă se află, de obicei, concentrat ă într-o structur ă numită
tabela de simboluri. În cea mai simpl ă formă, tabela de simboluri apare ca un
tablou de înregistr ări, dar există și alte forme de reprezenta re a sa: arbori, liste,
etc. Tabela de sim boluri este divizat ă în două părți :
− numele, care este un ș ir de caractere reprezentând identificatorul și
− informaț ia care con ține
• tipul identificatorului: intege r, real, record, array, etc.
• utilizarea sa : parametru formal, etichet ă, subprogram, etc. Curs 13
Durata :
2 ore
Generalit ăți cu
privire la structura și
utilizarea
Automate, limbaje și compilatoare
193
• domeniul de defini ție: pentru un tablou, de exemplu, num ărul dimensiunilor,
limitele fiecarei dimensiuni, etc.
• adresa de memorie, etc.
Aceast ă divizare a tabelei de simboluri se face cu scopul de a economisi
memorie. Numele simbolice devin la un moment dat inutile, cum se întâmpl ă la
ieșirea din domeniul de valabi litate al variabilelor de semnate prin aceste nume.
Spațiul folosit pentru p ăstrarea numelor poate fi reutilizat în cazul când numele
memorate nu mai apar în program. Tabela de simboluri poate fi constituit ă dintr-o
mulțime de tabele, fie specializate pentru va riabile, proceduri, constante, etichete,
etc., fie diferen țiate pe baza lungimii numelui simbolic: tabele cu nume de cel
mult patru caractere, tabele cu num e de cel mult 5-8 caractere, etc.
Tabela de simboluri este utilizat ă în diferite faze ale compil ării:
− în faza de analiz ă lexicală și sintactic ă, când, la întîlnirea unui nume în
program, compilatorul (de obicei analizorul lexical) verific ă dacă numele
respectiv se afl ă memorat sau nu în tabel ă. Dacă numele nu se afl ă în tabelă, el
este introdus, re ținîndu-se adresa intr ării;
− în faza de analiz ă semantic ă, pentru a verifica dac ă utilizarea identificatorilor
este în concordan ță cu declaraț iile;
− în faza generă rii de cod pentru a determina lungimea zonelor de memorie
alocate variabilelor;
− în faza de tratare a erorilor, pentru a evita mesaje redundante.
Diferitele ac țiuni executate de compilator asupra tabelei de simboluri
sunt:
− verificarea dac ă un nume este întâlnit pentru prima dat ă sau nu;
− adăugarea unui nume întâlnit pentru prima dat ă;
− adăugarea unei informa ții la un nume;
− ștergerea unui nume sau grup de nume.
Deoarece performan țele unui compilator depind în mare m ăsură de
eficiența căutării în tabela de simboluri, iar c ăutarea are loc pentru fiecare simbol
întâlnit, este foarte important ă metoda de organizare a tabelei de simboluri.
II.8.2. Organizarea tabelei de simboluri
O prim ă clasificare a tabelei de simboluri este dat ă de existen ța sau
inexistența unor criterii de c ăutare în tabel ă. Dacă asemenea criterii nu exist ă,
tabela este neordonat ă; dacă există un mecanism care s ă grăbească găsirea unui tabelei de
simboluri
Automate, limbaje și compilatoare
194
simbol în tabel ă, aceasta este ordonat ă. Tabelele ordonate se clasific ă la rândul lor
după mecanismul folosit pentru accesul la intr ări.
II.8.2.1. Tabele neordonate
Organizarea cea mai simpl ă a unei tabele de simboluri const ă în adăugarea
secvențială de noi intr ări pe măsură ce ele apar, în ordinea apari ției. Organizarea
tabelei de simboluri depinde de limbaj. Pentru un limbaj ce impune o lungime
maximă asupra numelor, memorarea va fi diferit ă față de un limbaj care nu
impune această cerință.
Când lungimea este limitat ă, se poate rezerva un spa țiu maxim pentru a
memora numele. Implementarea se face ca în figura 8.1.
Nume Informa ții
Identif1 întreg,……, variabila simpl ă
A șir,……., etichetă
B real,….., variabilă simplă
Figura 8.1
Când lungimea nu este limitat ă, nu ne putem permite s ă rezervăm un
spațiu maxim pentru a stoca numele, deoarece spa țiul pierdut ar fi prea mare. În
acest caz vom stoca numele sub forma unui pointer c ătre tabela numelor. Vom
avea, deci dou ă tabele: una care con ține numele ș i alta care con ține informa țiile și
pointerii c ătre prima. Lungimea numelor se stocheaz ă în tabela informa țiilor sau
în tabela numelor sau va fi implicit ă.
Dezavantajul reprezent ării tabelei de simboluri sub form ă de tablou const ă
în faptul că pentru identificarea unui nume este necesar ă căutarea sa începând cu
prima înregistrare pân ă când este g ăsit sau pân ă la sfârșit. Căutarea poate fi
optimizat ă dacă plasăm cele mai frecvent utilizate nume la începutul tabelei.
Pentru aceasta se supra pune peste structura secven țială a tabelei, o structur ă de
listă, ca în figura urm ătoare. În acest caz, c ăutarea se face în ordinea dat ă de
legături.
Tabele
neordonate
Automate, limbaje și compilatoare
195
Figura 8.2
II.8.2.2. Tabele ordonate alfabetic
În tabelele ordonate alfabetic ordinea intr ărilor este dat ă de ordinea
alfabetică a numelor. Dac ă tabela este un tablou de înregistră ri, cea mai adecvat ă
căutare este cea binar ă. Presupunând c ă sunt ocupate intrări din tabel ă,
căutarea se face cu func ția Caută_bin(x,k) n
p←1
u←n
gă sit← fals
repeat
i← [(p+u)/2]
if x<Nume[i]
then u← i-1
else if x>Nume[i]
then p← i+1
else begin
gă sit← true
k ← i
end
until găsit or p>u
if not gă sit then k←0
Algoritmul de căutare binar ă
într-o tabel ă
ordonată
alfabetic
Automate, limbaje și compilatoare
196
unde [ reprezint ă partea întreag ă a lui ]x x.
Procedura prime ște la intrare numele x și întoarce indexul k al intrării în
care a găsit numele sau =0, dacă nu l-a g ăsit. Înregistr ările din tabel ă sunt
având numele . k
nR , , R , RL2 1 n Nume , Nume , Nume2 1 ,L
II.8.2.3. Tabele arborescente
Unele compilatoare folosesc arbor i binari pentru reprezentarea
simbolurilor. Fiecare nod reprezintă o intrare în tabel ă; el conține pe lâng ă nume
și atribute, o leg ătură spre stânga ș i una spre dreapta c ătre arborii ce con țin nume
„mai mici“ și respectiv „mai mari“ decât numel e respectiv, în ordinea alfabetic ă
(figura 8.3).
……………… f
………………
/ \
/ \
/ \
……………. ……………….
b m
…………….. ……………….
/ \ / \
/ \ / \
……………… ………………. …………….. ………………
an comp form1 x3
……………… ………………… ……………… ………………..
/
/
/
…………………………..
Craiova
……………………………
Figura 8.3
Exemplu de implementare
a unei tabele
arborescente
Automate, limbaje și compilatoare
197
II. 8.2.4. Tabele dispersate
Metoda de că utare prin dispersie folose ște o funcț ie de dispersie care
aplicată la un identificator produce o valoare întreag ă nenegativ ă numită indexul
de dispersie al identificatorului. Prin func ția de dispersie, mulț imea
identificatorilor este parti ționată într-un anumit num ăr de clase, identificatorilor
dintr-o clas ă corespunzându-le acela și index de dispersie.
O funcție de dispersie bun ă trebuie s ă fie uș or de calculat și să creeze
clase echilibrate din punct de vedere al num ărului de identificatori ce-l con țin.
Prin dispersie, timpul de c ăutare al unui identificator se reduce la timpul de calcul
al indexului identificatorului ș i la timpul de c ăutare într-o singur ă clasă .
Func țiile de dispersie folosite în pr oiectarea tabelelo r de simboluri
prelucreaz ă de obicei repr ezentarea intern ă a șirului de caractere ce formeaz ă
identificatorul. Iată două astfel de func ții:
a) index cuprins între 0 și 255
− se adună ultimii 4 bi ți ai primelor dou ă caractere ale identificatorului
− la rezultat se adun ă lungimea identificatorului înmul țită cu 16
− se rețin ultimii 8 bi ți ai rezultatului.
b) index cuprins intre 0 si 210 ( și calculator avînd cuvânt ul de memorie format
din 4 octe ți)
− se adună cuvintele ce con țin caracterele identificatorului
− se împarte rezultatul la 211 și se reț ine restul.
Dac ă funcția de dispersie este bun ă, iar numărul indecșilor este destul de
mare, este posibil ca, într-un program nu prea lung, s ă se disperseze pentru
fiecare index cel mult un identificator. În general, îns ă, nu putem evita
dispersarea a mai mult de un identific ator pentru un index, fenomen numit
coliziune. Principala tehnic ă de rezolvare a coliziunilor este înl ănțuirea, care
poate fi utilizat ă sub diverse forme; ne vom opri la cea numit ă înlănțuire separat ă.
Această metodă implică înlănțuirea înregistr ărilor ce colizioneaz ă, într-o zon ă
specială, separată de prima, conform figurii 8.4.
Funcții de
dispersie
Automate, limbaje și compilatoare
198
Figura 8.4
II.8.3. Reprezentarea identificatorilor ținând seama de
domeniul de valabilitate
În majoritatea limbajelor de programare, în cadrul unui program se poate
folosi acela și identificator pentru a desemna variabile diferite, cu atribute diferite
și zone de memorie diferite, alocate în faza de execu ție. Tabela de simboluri
trebuie să păstreze pentru fiecare variabil ă intrări distincte. Deci, trebuie s ă existe
un mecanism care la apari ția unui identificator s ă selecteze intrarea corect ă din
mulțimea intr ărilor ce con țin același nume simbolic. Dar, semnifica ția unei
variabile rezult ă din modul în care se stabile ște domeniul de valabilitate al
variabilelor din limbajul respectiv. Aceasta se poate realiza ținînd seama de
blocul în care apare identificatorul resp ectiv. Un identificator va fi reprezentat
prin numele să u și prin num ărul blocului în care a fost declarat. Acest num ăr nu
apare obligatoriu în mod explicit; el poate fi dedus plecând de la poziț ia
identificatorului în ta bela de simboluri.
Pentru a determina domeniul de va labilitate al unui identificator se
defineș te noțiunea de bloc activ sau inactiv. Un bloc este activ atâta timp cât nu a
fost întâlnit sfâr șitul său. Când se analizeaz ă procedura 4 din figura 8.5,
procedurile 1, 2 și 4 sunt active, iar 3 este inactiv ă.
Tabela dispersată
Automate, limbaje și compilatoare
199
PROCEDURE _ _
_ _ BEGIN
| PROCEDURE _ _
| __ BEGIN
| | PROCEDURE _ _
| | __ BEGIN
| | | •
| | 3| •
| | | •
| | –- END
1 | 2 | PROCEDURE _ _
| | __ BEGIN
| | | •
| | 4| •
| | | •
| | – END
| – END
– END
Figura 8.5
Analiza lexical ă folosește identificatorul unei variabile pentru a c ăuta
descrierea sa în tabela de simboluri. O dat ă găsită, identificatorul poate fi înlocuit
cu un indicator la aceast ă intrare ce va fi utilizat în generarea codului intermediar.
După analiza zonei ce reprezint ă domeniul de valabil itate al unei variabile,
memorarea identificatorului nu mai este necesar ă; rămîn necesare în continuare
atributele. Referin țele din codul intermediar vor fi spre aceast ă parte și nu
neapărat spre numele simbolic, care poate lipsi.
Pentru limbajele de tip “bloc” (de exemplu, PASCAL, C ) trebuie ținut cont de
incluziunea unul în altul a domeniilor de va labilitate reprezentate de blocuri,
proceduri, cicluri. La întâlnir ea unui identificator, el trebuie c ăutat în declara țiile
celui mai apropiat bloc înconjur ător, iar dac ă nu este g ăsit este căutat în blocul
înconjurător acestuia ș . a. m. d. Deci, tabela de simboluri trebuie s ă reflecte
structura de bloc a limbajului. Este necesar ca: – orice început de bloc s ă deschidă un domeniu de valabilitate, deci o tabel ă de
simboluri locale blocului; – în orice moment trebuie s ă putem c ăuta nu numai în tabela de simboluri a
Structură de
tip bloc
Automate, limbaje și compilatoare
200
blocului curent, ci și în tabelele blocurilor înconjur ătoare; deci este necesar ă o
legătură între aceste tabele;
– la sfârș itul unui bloc, variabilele declarate în acest bloc devin inutile, deoarece
atributele lor sunt completate și pe durata analizei nu vor mai fi folosite; este
necesară stocarea lor în vederea f azelor ulterioare ale compil ării.
O soluț ie de implementare a unui program de tip Pascal este dat ă în figura
8.6.
begin
| begin
| | |
| | begin
| | 3 |
| | |
1| | end …
| 2 | begin
| | 4 |
| | |
| | end
| end | begin
| 5 |
| |
| end
end.
Tabela general ă de simboluri
Figura 8.6
Implementare
care ține
seama de
structura
blocurilor
Automate, limbaje și compilatoare
201
Tabela blocurilor p ăstrează (prin câmpul Tata ) înlă nțuirea blocurilor,
numărul de simboluri declarate în fiecare bloc (prin câmpul ) și adresa
din tabela de simboluri general ă la care începe tabela de simboluri dedicat ă
fiecărui bloc. În continuare vom da un al t exemplu de implementare folosind
tabele dispersate. Fiecare bloc prime ște un num ăr; acesta, împreun ă cu noț iunea
de bloc activ, permit determinarea coresponden ței între utilizarea unui
identificator și declararea sa. Când un bloc este de ja analizat el devine inactiv iar
variabilele locale lui nu pot fi utilizate în alte blocuri decât dac ă sunt redefinite.
Blocurile inactive pot fi e liminate din tabela de leg ături, dar informa ția lor trebuie
conservat ă pentru fazele urm ătoare. Nrsimb
Automate, limbaje și compilatoare
202
Teme Curs
Teste Autoevaluare
1. De ce se recomand ă divizarea tabelei de simboluri?………………….. 1 punct
2. Pentru ce este necesar ă tabela de simboluri în faza gener ării de
cod?……………………………………………………………………………………. 1 punct
3. Dați un exemplu de implementare a une i tabele neordonate care nu
foloseș te lungimea identifi catorilor……………………………… 2 puncte
4. Care este dezavantajul utiliz ării unei tabele arborescente? Dar
avantajul?……………………………………………………………………………. 2 puncte
5. Care este principala caracteristic ă a tabelelor dispersate? Dar
avantajul?……………………………………………………………………………. 1 punct
6. Ce informa ții se stocheaz ă în partea a doua a unei tabele
dispersate?………………………………………………………………………….. 1 punct
7. Prin ce se defineș te domeniul de valabilitate al unei
variabile?……………………………………………………………………………… 1 punct
Oficiu…………………………………………………………… 1 punct
Automate, limbaje și compilatoare
203
Răspunsuri
1. Pentru a economisi memorie
2. Pentru a determina lungimea zonelor de memorie alocate
3.
Nume Informa ție
întreg,….., variabil ă simplă
șir,….., etichetă
real,……, variabilă simplă
8identif1 1A 7Element
4. Dezavantaj: poate genera arbori dezechilibra ți. Avantaj: este foarte util ă în
optimizarea codului
5. Realizeaz ă împărțirea identificatorilor în clase. C ăutarea secven țială se
face doar la nivelul unei clase
6. Cele care colizioneaz ă cu cele din prima
7. Prin blocul cel mai interior care o con ține
Rezumat: S-au prezentat modalit ăți de construire a tabelei de simboluri și de
gestionare a informa țiilor conținute .
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se implementeaz ă metodele de creare si gestiune a tabelelor de simboluri
ordonate.
Teme Laborator/Seminar
1. Implementa ți algoritmul de utilizare a une i tabele de simboluri ordonat ă
Automate, limbaje și compilatoare
204
alfabetic.
2. Implementa ți algoritmul de lucru cu o tabel ă arborescent ă.
3. Implementa ți algoritmul de înl ănțuire separat ă.
Rezumat: se implementează algoritmi de utilizare a tabelei de simboluri
Automate, limbaje și compilatoare
205
Notații
Automate, limbaje și compilatoare
206
Curs 14 Tratarea erorilor
Descriere Generală
Se prezint ă sursele erorilor și principalele erori care se întâlnesc în fazele de
analiză lexicală, sintactic ă, semantic ă și la executarea programelor.
Obiective
Cunoașterea surselor și a principalelor tipuri de erori care apar în faza de
compilare și execuție a programelor
Cuprins
II.9.1 Sursele erorilor
II.9.2 Erori în analiza lexical ă
II.9.3 Erori în analiza sintactic ă
II.9.4 Erori semantice
Conținut Curs
.
II.9.1 Sursele erorilor
Programele pe care le scriem s unt rareori corecte; ele prezintă diferite
tipuri de erori pe care compilatorul trebuie s ă le detecteze și să le semnaleze clar.
Un mesaj de eroare trebuie :
– să se exprime în termenii programului surs ă și nu în termeni lega ți de
reprezentarea intern ă
– să localizeze corect eroa rea; este corect mesajul ,, identificatorul ID n-a fost
declarat în procedura PROC “ și nu ,, lipse ște declararea identificatorului ID “
– să nu fie redundant.
Strategia utilizat ă de majoritatea compilatoarelor const ă în afiș area liniei
eronate cu un marcator pe locul unde a fost detectat ă eroarea. Eroarea real ă se
găsește, în general, fie în locul marcat, fie cu câteva simboluri mai în fa ță. În
unele cazuri compilatorul nu poate s ă dea nici-o informa ție cu privire la eroarea
întâlnită ; de exemplu, cazul când cuvântul cheie END este omis ( în Pascal ). Curs 14
Durata :
2 ore
Automate, limbaje și compilatoare
207
Erorile unui program pot fi detectate fie la compilare, fie la execu ție,
diferitele surse de erori fiind :
– erori generate de compilator; ele sunt detectate, în general, la execu ție, dar din
fericire sunt foarte rare ; – erori datorate limitelor compilatorului ( dimensiunea mare a programului
compilat, num ărul maxim de simboluri stocate în tabela de simboluri, etc ) ,
limite ce nu apar în specificarea limbajului; – erori lexicale; ele corespund inser ării sau absen ței unui caracter sau înlocuirii
unui caracter prin altul. Aceste erori sunt u șor de detectat și recuperat .
– erori sintactice și semantice; compilatorul poate corecta unele din ele.
Erorile sintactice sunt de tectate în faza de analiz ă lexicală și sintactic ă.
Exemplele de mai jos ne dau o imagine general ă asupra acestor tipuri de erori :
– eroare de punctua ție : utilizarea virgulei în loc de punct și virgulă
Function f ( x : integer , y : integer ) : real ;
– eroare de inserare :
if x :
= y then writeln (x) else writeln ( y) ;
sau if x = y then writeln (x) ; else writeln (y) ;
– erori dificil de semnalat if x
= 2+y-x ) then writeln (x) else writeln (y) ;
În această instrucțiune simbolul „ )“ este în plus sau lipse ște „(“. Aceste erori
sunt dificil de corectat, trebuind s ă ghicim intenț ia programatorului;
– erori detectate mai târziu if x +2-y
= y then writeln (x) else writeln ( y) ;
În acest caz lipse ște un spațiu între if și variabila x. Această eroare este detectat ă
la întâlnirea caracterului „t“ al lui then. Erorile de acest tip nu pot fi detectate
imediat, fiind necesar un mijloc de a le repera și de a reveni la locul unde au fost
detectate. Dac ă prezența separatorilor este obligatorie, la întâlnirea lui ,, if “,
compilatorul va afi șa mesajul „identificator nedeclarat“. Erorile semantice sunt
detectate la :
– compilare , în timpul fazei de analiz ă sintactică :
• incompatibilitate de tip între operanzi și operatori, între parametrii
actuali și cei formali, etc.
• identificator nedeclarat sau multiplu declarat
– la execu ție
• împărțirea prin zero
• citirea unui fi șier după închiderea sa
Surse ale erorilor
Exemple de
erori
sintactice
Exemple de erori
semantice
Automate, limbaje și compilatoare
208
• afectarea unei valori care nu apar ține domeniului unei variabile: indice
de tablouri , selectorul instruc țiunii case , etc .
Recuperarea erorilor . Odată detectată o eroare, compilatorul trebuie s-o
semnaleze programatorului și să încerce s-o repare. Compilatoarele difer ă după
metoda de reparare a erorilor și după maniera de continuare a analizei dup ă
apariția unei erori. Exist ă compilatoare care realizeaz ă :
– redresarea : toate activit ățile compilatorului, altele decât analiza lexical ă și
sintactică, încetează după detectarea primei erori. Majoritatea compilatoarelor
lucrează în această manieră .
– recuperarea : un compilator mai complex caut ă să repare eroarea, adic ă să
transforme intrarea eronat ă într-una echivalentă , dar autorizat ă. Totuși, rezultatul
nu este întotdeauna cel scontat; recuperarea unei erori sintactice poate duce la una
semantică.
– corectarea : un compilator și mai complex caut ă să corecteze intrarea eronat ă
încercând s ă ghicească intenția programatorului; un ex emplu este compilatorul
PL/C. Aceste corec ții pot fi efectuate îns ă pentru un domeniu re strâns de erori.
II.9.2 Erori în analiza lexical ă
Analizorul lexical este un automat finit; simbolurile de intrare îi permit
trecerea de la o stare la alta. Dac ă s-a ajuns în starea final ă, a fost recunoscut un
atom lexical. Dacă automatul se blocheaz ă pe stare nefinală , trebuie invocat ă o
rutină de tratare a erorilor. Din p ăcate, acestea nu dispun de solu ții miraculoase.
Când un simbol de intrare nu permite ni ci-o trecere, unele rutine îl ignor ă, iar
altele îl înlocuiesc printr-unul ce permite trecerea.
O soluție mai elaborat ă constă în existen ța unui dialog între analizorul
lexical și cel sintactic. De exemplu, analizorul sintactic poate cere celui lexical ca
următorul atom s ă aparț ină unei anumite clase de atomi. Astfel, analizorul lexical
este orientat în c ăutarea dar și în repararea erorii. La rândul s ău, analizorul lexical
poate raporta analizorului sintact ic tipul eventualelor transform ări presupuse de
repararea erorii.
O categorie frecvent întâlnit ă de erori detectate de analizorul lexical se
datorează scrierii greș ite a cuvintelor cheie. Repararea este în acest caz posibil ă
datorită numărului relativ mic de posibilit ăți de reparare. Tratamentul este dificil
pentru erori de tipul :
– câmp : = „acesta este un șir
Eliminarea erorilor
Tratarea
erorilor
lexicale
Automate, limbaje și compilatoare
209
când apostroful final este omis ;
– expresie : = AB
când este omis operatorul, AB fiind luat ca identificator.
II.9.3 Erori în analiza sintactic ă
Erorile detectate în timpul analizei lexicale nu sunt obligatoriu erori
sintactice propriu-zise. De exemplu instruc țiunea
if x = y then writeln ( x) ; else writeln ( y) ;
conține un punct și virgulă inutil. Aceast ă eroare va fi detectat ă de analizorul
lexical, dar ea este o eroare de inserare. Exist ă mai multe metode de tratare a
erorilor sintactice .
Recuperarea în mod panică este metoda cea mai folosit ă și cea mai u șor
de implementat, fiind utilizat ă de toate tipurile de analizori, f ără nici-o condi ție.
Când este întâlnit un s imbol eronat, se înl ătură simbolurile urm ătoare pân ă se
întâlnește unul de sincronizare cum sunt punct și virgulă sau end. Se procedeaz ă
la fel ș i cu simbolurile di n vârful stivei.
Ștergerea de simboluri constă în ștergerea tuturor simbolurilor de intrare
care nu dau o acț iune legală de executat. La fel ca precedenta, aceast ă metodă
ignorează erorile ce pot apare datorit ă simbolurilor ș terse.
Inserarea de simboluri . Când un simbol de intrare, combinat cu cel din
vârful stivei, nu d ă o acțiune legal ă, se insereaz ă la intrare un simbol care d ă o
astfel de ac țiune .
Tratarea erorilor în analiza LL (1)
Poate fi aplicat ă oricare din metodele anterioare, dar strategia cea mai
importantă constă în completarea c ăsuțelor libere din tabloul de analiz ă cu
pointeri c ătre rutinele de tratare a erorilor. Aceste rutine au dou ă funcț ii
– schimbă, insereaz ă sau suprim ă simboluri din cîmpul de intrare
– modifică, în mod corespunz ător, stiva .
II.9.4 Erori semantice
Sursa principală a erorilor semantice o constituie utilizarea incorect ă a
identificatorilor sau a e xpresiilor ce desemneaz ă variabilele din program. Prima
întâlnire a unui asemenea identificator sau expresie trebuie s ă determine afi șarea
Tratarea erorilor de
sintaxă
Automate, limbaje și compilatoare
210
unui mesaj de eroare dar și înregistrarea sa în tabela de simboluri. Aceast ă
înregistrare este necesar ă în vederea viitoarelor întâlniri ale acestui identificator:
o operaț ie identic ă din punct de vedere al atributelor nu trebuie s ă provoace
emiterea aceluia și mesaj, iar apari țiile distincte trebuie înregistrate în tabel ă.
Problema recuper ării din erori semantice este legat ă de suprimarea unor mesaje
de eroare.
a) Mesajele datorate recuper ării defectuoase a unui identificator sau
expresii trebuie suprimate. Cazul cel mai frecvent este cel al variabilelor indexate
de forma în cazul când nu a fost declarat ca tablou sau
declarația a fost gre șită și, deci, ignorată . La întâlnirea lui „ [ “ se dă un mesaj
privind incompatibilitatea folosirii lui [nind , , ind , ind AL2 1] A
A
A în raport cu declarara ția. De
asemenea la întâlnirea lui „ ]“ analizorul va verifica num ărul de dimensiuni cu cel
declarat; neconcordan ța va determina emiterea unui nou mesaj. În cazul când
identificatorul eronat este in terpretat ca unul corect, se creaz ă o intrare în tabela
de simboluri având ca valori de atribut cele rezultate din contextul utiliz ării. În
cazul prezentat anterior, intrarea va con ține pentru atributele ,,tip identificator“ și
„număr dimensiuni“ va lorile „tablou“ și . La întâlnirea unei situa ții de eroare
datorate acestei ,,corect ări“ , faptul c ă vom căuta în înregistrarea corectat ă și nu
în una normal ă, permite s ă evităm tipărirea mesajului. n
b) Mesajele datorate utiliz ării incorecte de mai multe ori a aceluia și
identificator sau expresii trebuie suprimate. Cazul cel mai frecvent este cel al
omiterii declara țiilor. Apari ția repetat ă a unui identificator nedeclarat poate
determina emiterea de mai multe ori a aceluia și mesaj de eroare. Prima apari ție a
unui astfel de identificator trebuie s ă determine formarea unei intr ări în tabela de
simboluri, dedicat ă identificatorului. At ributele asociate intr ării sunt cele rezultate
din context. La întâlnirea identificatorului în aceea și situație, nu se va mai emite
mesaj de eroare. Dac ă identificatorul este folosit și în alte situa ții (de exemplu,
este de alt tip), acestea trebuie memorate pentru a se evita mesaje identice. În
acest scop , intrarea oric ărui identificator va con ține și un indicator spre o list ă a
tuturor modurilor incorecte în care a fo st folosit identificatorul. Lista aceasta
serveș te pentru a tip ări doar mesajele de erori distincte.
Tratarea
erorilor semantice
Automate, limbaje și compilatoare
211
Teme Curs
Teste Autoevaluare
1. Care sunt caracteristicile me sajului de eroare…………………………. 2 puncte
2. Care sunt sursele erorilor?……………………………………………………. 2 puncte
3. Când se detecteaz ă erorile sintactice……………………………………….1 punct
4. Când se detecteaz ă erorile semantice………………………………………1 punct
5. Care sunt metodele de reparare a erorilor?……………………………… 1 punct
6. Care sunt metodele de tratare a erorilor sintactice si in ce
consta?……………………………………………………………………………… 2 puncte
Oficiu………………………………………………………………… 1 punct
Automate, limbaje și compilatoare
212
Răspunsuri
1. – să se exprime în termenii programului surs ă și nu în termeni lega ți de
reprezentarea intern ă
– să localizeze corect eroarea
– să nu fie redundant .
2. – erori generate de compilator; ele s unt detectate, în general, la execu ție, dar
din fericire sunt foarte rare ;
– erori datorate limitelor compilatorului ( dimensiunea mare a programului
compilat, num ărul maxim de simboluri stocate în tabela de simboluri, etc ) ,
limite ce nu apar în specificarea limbajului; – erori lexicale; ele corespund inser ării sau absen ței unui caracter sau înlocuirii
unui caracter prin altul. Aceste erori sunt u șor de detectat și recuperat .
– erori sintactice și semantice; compilatorul poate corecta unele din ele.
3. În fazele de analiz ă lexicală și sintactică
4. La analiza sintactic ă și la execu ție
5. Redresarea, recuperarea și corectarea
6.
Recuperarea în mod panică : când este întâlnit un simbol eronat, se înl ătură
simbolurile urm ătoare pân ă se întâlneș te unul de sincronizare cum sunt punct și
virgulă sau end.
Stergerea de simboluri constă în ștergerea tuturor simbolurilor de intrare care
nu dau o ac țiune legal ă de executat.
Inserarea de simboluri . Când un simbol de intrare, combinat cu cel din vârful
stivei, nu dă o acț iune legal ă, se insereaz ă la intrare un simbol care d ă o astfel de
acțiune
Rezumat: S-au prezentat modalit ăți de tratare a erorilor întâlnite în fazele de
analiză.
Automate, limbaje și compilatoare
213
Lucrari Practice (Laborator/Seminar)
Conținut Laborator/Seminar
Se implementeaz ă un algoritm care s ă corecteze erorile sintactice prin una din
metodele: recuperare în mod panic ă, ștergere de simboluri, inserare de simboluri
Teme Laborator/Seminar
1. Scrieți un program care s ă elimine erorile din analiz ă lexicală
Rezumat: se implementează un algoritm de corectare a erorilor sintactice
Automate, limbaje și compilatoare
214
Notații
Automate, limbaje și compilatoare
215
Automate, limbaje și compilatoare
216
Automate, limbaje și compilatoare
217 BIBLIOGRAFIE
[1] A. V. Aho, R. Sethi, J. D. Ullman: Compilers, Principles, techniques and tools,
Addison-Wesley, 1986
[2] A. Dinc ă, M. Andrei: Limbaje formale, Ed itura Universitaria, Craiova, 2002
[3] D. Gries, Compiler construction for di gital computers, Wi ley and Sons, New
York, 1971 [4] A. Hajjam El Hassani, Les compilateurs el leur principes, Edition Scientifiques et
Techniques, Ecole Superieure des Sciences Appliquees pour l’Ingenieurs,
Mulhouse, 1993 [5] I. Iancu : Teoria compilatoarelor, Editura « Vlad & Vlad«, Craiova, 1997
[6] I. Iancu, M. Andrei: Teoria compilato arelor si semantica limbajelor de
programare. Indrumar de laborato r, Reprografia Universitatii din Craiova, 1998.
[7] I. Iancu: Proiectarea compilatoarel or , Editura Universitaria, Craiova, 2002
[8] C. Ionescu Texe, I. Zsako: Structuri arborescente si ap licatiile lor, Ed. Tehnica,
Bucuresti, 1990 [9] L. Livovschi, C. Popovici, H. Georgescu, N. Țăndăreanu : Bazele informaticii,
Editura Didactic ă și Pedagogic ă, București, 1981
[10] A. B. Pyster, Compile r design and construction. T ools and techniques, Van
Nostrand Reinhold, New York, 1988 [11] L. D. Șerbănați, Limbaje de programare și compilatoare, Editura Academiei,
Bucure ști, 1987
[12] J. P. Tremblay, P. G. Sorenson, Th e theory and practice of compiler writing,
McGraw-Hill, Inc., New York, 1985
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Seria RCAI Învățământ la Distan ță [622467] (ID: 622467)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
