Sunteți pe pagina 1din 143

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

INTRODUCERE - ORGANIZAREA UNUI COMPILATOR


Analiza lexicala Analiza sintactic Analiza semantic Generarea de cod intermediar Optimizarea codului intermediar Generarea codului obiect Optimizarea codului obiect Gestiunea tabelei de simboli Detectarea erorilor

3
4 4 5 5 6 6 6 6 6

1. ELEMENTE DE TEORIA LIMBAJELOR FORMALE


1.1. Gramatici Ierarhia Chomsky. Exerciii 1.1.1. Verificarea limbajului generat de ctre o gramatic 1.1.2. Transformri asupra gramaticilor independente de context a. Eliminarea ambiguitii b. Eliminarea - produciilor c. Eliminarea recursivitatii stnga d. Factorizare stnga e. Eliminarea simbolilor neterminali neutilizai g. Substituia de nceputuri(corner substitution) 1.1.3. Construcii dependente de context Exerciii 1.1.4. Propieti ale limbajelor independente de context 1.2. Mulimi regulate, expresii regulate.

7
8 9 10 11 12 13 16 17 19 20 21 23 24 25 26

1.3. Acceptoare 29 1.3.1. Automate finite 30 1.3.1.1. Construcia unui automat finit nedeterminist care accept limbajul descris de o expresie regulat dat 32 1.3.1.2. Conversia unui automat finit nedeterminist (AFN) ntr-un automat finit determinist(AFD)36 1.3.1.3. Construcia unui automat finit determinist care accept limbajul descris de o expresie regulat dat 39 1.3.1.4. Simularea unui automat finit determinist 45 1.3.1.5. Simularea unui automat finit nedeterminist 46 1.3.1.6. Probleme de implementare pentru automatele finite deterministe i nedeterministe 47 1.3.1.7. Minimizarea numrului de stari pentru AFD 48 1.3.2. Automate cu stiv(pushdown) 51 1.3.3 Maina Turing 60 1.3.3.1. Compunerea mainilor Turing 66 1.3.3.2. Extensii pentru maina Turing 70 1.3.3.3. Automate liniar mrginite 75 1.3.3.4. Relaia ntre maina Turing i gramatici 76 1.3.3.5. Elemente de calculabilitate 80 Maina Turing Universal 80 1.3.3.6. Maina Turing cu limit de timp 84

2. ANALIZA LEXICAL

87
1

Irina Athanasiu
2.1. Interfaa analizorului lexical

10/4/2003

Limbaje formale si translatoare

2
90 92

2.2. Un exemplu elementar de analizor lexical

3. ANALIZA SINTACTIC
3.1. Analiza sintactica top - down 3.1.1. Analiza sintactica predictiva (descendent recursiva) 3.1.1.2. Gramatici LL(1) 3.1.1.3. Tratarea erorilor n analiza predictiv 3.1.2. Analiza sintactica bottom-up 3.1.2.1. Analiza sintactica de tip deplaseaza i reduce

101
105 106 110 115 117 117

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

Introducere - organizarea unui compilator


Un compilator este un program complex care realizeaz traducerea unui program surs ntr-un program obiect. De obicei programul surs este scris ntr-un limbaj de nivel superior celui n care este scris programul obiect. Structura general pentru un compilator este:
program sursa | +-----------------+ | preprocesor | pas 1 +-----------------+ | pas 2 - - - - - - - | - - - - - - - - - - - - - - - - - - - - - - + | | | | +------------------+ +--------------------+ | | analiza lexicala |--------->| analiza sintactica | | | |<---------| | | +------------------+ +--------------------+ | | | | | +------------------+ +--------------------+ | | gestiunea tabelei| | analiza semantica | | | de simboli |<---------| | | +------------------+ +--------------------+ | | | | | +--------------------+ | +------------------->| generarea de cod | | | intermediar | | +--------------------+ | - - - - - - - - - - - - - - - - - - - - - - | - - - - - - -+ | cod intermediar | +--------------------+ pas 3 | optimizare | | cod intermediar | +--------------------+ | | cod intermediar +--------------------+ pas 4 | generarea de cod | | obiect | +--------------------+ | | cod obiect +--------------------+ pas 5 | optimizare | | cod obiect | +--------------------+ | limbaj de asamblare sau cod masina

+ | | | | | | | | | | | | | | | | +

Preprocesorul realizeaz activitai de tip macro substituie, eliminarea comentarilor, etc. Al doilea pas reprezint de fapt componenta principal a compilatorului (celelalte componente ar putea s lipseasc). Efectul execuiei acestui pas const din verificarea corectitudinii formale a textului programului i traducerea acestui text ntr-o form intermediar. Urmtorii trei pai realizeaz prelucrri asupra programului n cod intermediar n scopul imbuntirii performanelor acestuia (optimizarea) i generrii programului obiect. Pasul cel mai complex dintr-un compilator rmne pasul 2 n care se realizeaz cele mai importante operaii fr de care nu poate avea loc procesul de compilare. ntr-un compilator real cele cinci componente care l formeaz : analiza lexical, analiza sintactic, analiza semantic, gestiunea tabelei de simboli i generarea de cod nu sunt neaprat identificabile sub

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

forma unor proceduri ori funcii distincte ci sunt realizate printr-un ansamblu de funcii care coopereaz. n cele ce urmeaz aceste componente vor fi descrise separat pentru simplificarea expunerii.

Analiza lexicala
Aceast faz a compilatorului realizeaz traducerea textului programului ntr-o forma mai uor de prelucrat de ctre celelalte componente. Analizorul lexical consider textul primit la intrare ca find format din uniti lexicale pe care le recunoate producnd atomi lexicali. Un atom lexical poate s fie de exemplu, un cuvnt cheie al limbajului (for, while, etc) dar i un numr sau un nume. Nu exist o coresponden biunivoc ntre irurile de intrare i atomii lexicali. Adic, dac pentru atomul lexical corespunztor cuvintului cheie while exist un singur ir de intrare, pentru atomul lexical corespunztor unui numr intreg pot s existe foarte multe iruri de intrare. Una dintre decizile ce trebuie luate la nceputul proiectrii unui compilator const din stabilirea atomilor lexicali. De exemplu, se pune problema dac s existe cte un atom lexical pentru fiecare operator de comparaie (<, <=, >, >=) sau s existe un unic atom lexical - corespunztor operaiei de comparaie. n primul caz generarea de cod poate s fie mai simpl. Pe de alt parte existena unui numr mare de atomi lexicali poate complica n mod exagerat analiza sintactic. n general, operatorii care au aceai prioritate i asociativitate pot s fie grupati impreun. Rolul unui analizor lexical este de a traduce irurile de intrare n atomi lexicali. Un atom lexical este reprezentat printr-un cod numeric care specifica clasa acestuia i o serie de atribute care sunt specifice fiecrei clase. Astfel, poate s existe clasa operatorilor relationali pentru care un atribut trebuie s se specifice tipul concret al operatorului. Tipul atomului lexical este necesar pentru analiza sintactic n timp ce valoarea atributului este semnificativ pentru analiza semantic i generarea de cod. Pentru un atom lexical de tip numr atributele vor descrie tipul numrului i valoarea acestuia. Un analizor lexical apare n general ca o funcie care interfacioneaz cu restul compilatorului printr-o interfa simpl : ori de cte ori analizorul sintactic are nevoie de un nou atom lexical va apela analizorul lexical care i va da atomul lexical urmtor.

Analiza sintactic
Analiza sintactic descompune textul programului sursa n componentele sale "gramaticale", construind un arbore care reflect aceast structur. S considerm de exemplu expresia :
A*B+C*D

Aceast expresie poate s fie descris de urmtorul tip de arbore numit arbore sintactic:
+ / \ / \ / \ * * / \ / \ / \ / \ A BC D

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

n acest arbore au fost evideniate relaiile (din punctul de vedere al modului de evaluare) ntre componentele expresiei. Dac se dorete ns s se evidenieze structura expresiei din punctul de vedere al unitiilor sintactice din care este format, atunci se va utiliza pentru reprezentarea expresiei un arbore de derivare (parse tree). Pentru exemplul considerat un arbore de derivare ar putea s fie de forma:
expresie /|\ expresie + expresie // / \ \\ // / \ \\ // / \\ expresie * expresie expresie * expresie | | | | nume nume nume nume | | | | A B C D

Orice analizor sintactic realizeaz traducerea unui ir de atomi lexicali ntr-un astfel de arbore de derivare care descrie relaia ierarhic ntre o descriere general a propoziiei analizate (rdcina arborelui) i irul de atomi lexicali din care este format (frunzele). Un analizor sintactic poate s construiasc efectiv o structur de date de tip arbore (cu pointeri i inregistrri) sau poate s sintetizeze informaiile din care se poate face construcia acestuia.

Analiza semantic
Aceast faz este de obicei incorporat n faza de analiz sintactic. Rolul acestei faze const din verificarea din punct de vedere semantic a structurilor recunoscute drept corecte din punct de vedere sintactic. Majoritatea verificrilor realizate de ctre aceast faz se refer la tipurile construcilor. De asemenea aceast faz completeaz arborele de derivare cu o serie de informaii necesare generrii de cod.

Generarea de cod intermediar


Nici aceasta faz nu este ntodeauna separat de analiza sintactic, exist compilatoare care genereaz cod chiar n timpul analizei sintactice. Generarea de cod se face prin parcurgerea arborelui de derivare. Forma intermediar care se genereaz reprezint codul obiect pentru o main virtual. Utilizarea formelor intermediare se justifica prin cteva argumente. n primul rnd anumite optimizari nu se pot face n timpul analizei sintactice i sunt dificil de realizat pe un text de program ntr-un limbaj de programare de nivel foarte sczut. De exemplu scoaterea expresiilor constante n afara ciclurilor. Alt motiv este utilizarea aceleeai faze de optimizare i generare de cod main pentru diferite limbaje de programare, respectiv utilizarea aceleai faze de analiza sintactic, semantic i generare de cod intermediar pentru a implementa acelai compilator (limbaj) pe maini diferite. Cu alte cuvinte pentru a realiza implementri portabile pentru compilatoare. De asemenea utilizarea unei maini virtuale permite realizarea mai simpl de compilatoare incrementale sau interpretoare performante. Acest tip de translatoare execut direct (interpreteaz) codul intermediar fr a mai trece prin fazele urmtoare - editare de legturi, ncrcare, etc, dar i fr a recunoate de fiecare dat o instruciune care a fost deja tratat, cum s-ar ntmpla dac interpretarea s-ar face la nivel de limbaj surs. Dezavantajul utilizrii unei forme intermediare const n mod evident din mrirea timpului necesar pentru execuia unei compilri.

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

Optimizarea codului intermediar


Aceast faz identific optimizrile posibile asupra codului n limbaj intermediar. De exemplu pentru o secven ca:
for(....) { a[i * c] = b[i * d] + e + f; ... }

Se observ c o parte din calcule se pot efectua o singur dat nainte de ciclul for, rezultatele respective se pot memora n variabile temporare, etc. Desigur astfel de optimizri pot s fie fcute i de ctre programator. Este de preferat ns s se pstreze claritatea programului, iar acest tip de transformri s fie realizate de ctre compilator.

Generarea codului obiect


Aceast faz depinde de maina pentru care compilatorul trebuie s genereze cod i care poate s fie diferit de maina pe care se execut compilatorul (cazul cross compilatoarelor). Aceast faz depinde de arhitectura mainii int. Ideea este c pentru fiecare instruciune n limbaj intermediar se va alege o secven echivalent de instruciuni obiect.

Optimizarea codului obiect


i aceast faz depinde de maina pentru care se genereaz cod. i anume se identific secvene de cod main care pot s fie nlocuite cu instruciuni mai rapide. De exemplu pentru o main din familia '86 o instruciune: add ax, 1 poate s fie nlocuit cu inc ax, dac instruciunea care urmeaz modific indicatorul carry.

Gestiunea tabelei de simboli


n tabela de simboli se nregistreaz identificatorii utilizai n program i informaii asupra acestora. Aceste informaii pot s se refere la tip, domeniu de valabilitate; dac este vorba de identificatori de tip nume de funcie la aceste informaii se adaug i signatura funciei (numrul i tipul argumentelor, modul de transfer i eventual tipul rezultatului). n general o tabel de simboli este o structur de date care conine cte o nregistrare pentru fiecare identificator avnd cmpuri pentru atributele posibile. Introducerea simbolilor n tabela se face de ctre analizorul lexical. Atributele acestora sunt completate n tabela de ctre analizoarele sintactic i semantic.

Detectarea erorilor
Fiecare faz a unui compilator poate s identifice prezena unei erori specifice. De exemplu, n analiza lexical ntlnirea unui ir care nu corespunde unui atom lexical; n analiza sintactica se identific erori legate de structura instruciunilor. Ca de exemplu pentru irul:
int real alfa;

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

fiecare atom lexical n parte este corect dar nu formeaz mpreun o propoziie corect din punct de vedere sintactic. n faza de analiz semantic se verific dac construciile corecte din punct de vedere sintactic sunt corecte i din punct de vedere semantic. De exemplu dac la nivelul sintaxei poate s apara ca fiind corecta o expresie de forma: nume + nume, fr nici o restricie asupra tipului identificatorilor corespunztori, este rolul analizei semantice s identifice ca eronat o expresie n care primul nume este al unui vector iar al doilea nume este al unei proceduri. Problema cea mai dificil legat de tratarea erorilor const din modul n care se continu analiza dupa identificarea unei erori, pentru c un compilator care se oprete la prima eroare ntilnit nu este prea comod de utilizat. Excepie face modul de abordare utilizat n primele versiuni ale compilatorului pentru TURBO Pascal pentru care la ntlnirea unei erori se revine n regim de editare pentru corectarea acesteia.

1. Elemente de teoria limbajelor formale


Fie T o mulime de simboli denumita alfabet. Orice submulime a mulimii T* reprezint un limbaj asupra alfabetului T. Elementele limbajului se numesc propoziii. Dac limbajul este finit atunci el poate s fie definit prin enumerare. De exemplu considernd alfabetul B = {0, 1} atunci L = {01, 10, 101} este un limbaj. Mulimea cuvintelor din limbajul natural este i el un limbaj pentru care se poate pune problema enumerrii tuturor cuvintelor, chiar dac lista care ar rezulta este imens, deci este un limbaj reprezentabil prin enumerare. Dar cazul interesant este cel n care limbajul este infinit. S considerm de exemplu limbajul "irurilor formate din 0 i 1 a caror lungime este divizibila cu 3". Evident este vorba de un limbaj infinit. Textul prin care am specificat limbajul constituie o reprezentare finit a limbajului. Nu este singura soluie posibil de reprezentare finit. De exemplu dac notam cu L limbajul respectiv atunci:
L = { w {0,1}* | |w| mod 3 = 0}

este un alt mod de a specifica acelai limbaj. Se pune problema dac dndu-se un limbaj oarecare este posibil ntotdeauna construirea unei reprezentri finite. S considerm c o astfel de reprezentare finit se realizeaz utiliznd simboli dintr-un alfabet finit A. Se poate demonstra c mulimea A* este infinit numrabil (se poate construi o bijectie f : N A*). Deci exist o mulime infinit numrabil de reprezentri finite. Numrul de limbaje ce se pot construi utiliznd simboli dintr-un alfabet dat T, este 2|T|* deci mulimea limbajelor este infinit nenumrabila. Rezult deci c ar trebui s reprezentm un numr infinit nenumrabil de obiecte avnd la dispoziie numai un numr infinit numrabil de reprezentri. Din acest motiv nu orice limbaj va putea s fie reprezentabil ntr-un mod finit. Nu putem s oferim un exemplu de limbaj pentru care nu avem o reprezentare finit pentru c exemplul ar fi tocmai o reprezentare finit a limbajului respectiv. Spre norocul nostru, nu suntem interesai de toate limbajele ci numai de o clas mai mic a limbajelor infinite cu reprezentri finite. n general exist doua mecanisme distincte de definire finit a limbajelor: prin generare sau prin recunoatere. n primul caz este vorba de un "dispozitiv" care tie s genereze toate propoziiile din limbaj (i numai pe acestea) astfel nct alegnd orice propoziie din limbaj ntrun interval finit de timp dispozitivul va ajunge s genereze propoziia respectiv. n al doilea caz este vorba de un "dispozitiv" care tie s recunoasc (s accepte ca fiind corecte) propoziiile limbajului dat.

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

1.1. Gramatici
O gramatic reprezint cel mai important exemplu de generator de limbaje. Prin definiie o gramatic este G = (N, T, P, S) unde : N este o mulime finit de simboli numit mulimea simbolilor neterminali; T este o mulime finit de simboli numit mulimea simbolilor terminali, (T N = ); P este o submulime finit din (N T)* N (N T)* x (N T)*; numit mulimea producilor gramaticii. Un element (, ) P este notat cu i se numete producie. S N este un simbol special numit simbol de start al gramaticii G. n cele ce urmeaz vom utiliza o serie de notaii devenite "clasice". i anume : literele mici de la nceputul alfabetului latin (a,b,c,...) reprezint elemente din T (simboli terminali); literele mici de la sfritul alfabetului latin (u, v, x,...) reprezint elemente din T* (iruri de simboli terminali); literele mari de la inceputul alfabetului latin (A, B, C,...) reprezint elemente din N (simboli neterminali); literele mari de la sfritul alfabetului latin (, V, X,...) reprezint elemente din N T (simboli terminali sau neterminali); literele alfabetului grecesc (, , ...) reprezint iruri din (N T)* (iruri de simboli terminali i neterminali). O form propoziional pentru o gramatic G se definete recursiv n modul urmtor: (1) S este o form propoziional; (2) dac este o forma propoziional i exist o producie atunci este o form propoziional. O form propoziional care conine numai simboli terminali se numete propoziie generat de G. Notm cu L(G) mulimea tuturor propoziiilor generate de G altfel spus L(G) este limbajul generat de gramatica G. Se observ c o gramatic este o reprezentare finit (toate elementele sale sunt finite) pentru un limbaj care poate s fie infinit. Conform observaiei fcute la nceputul acestui capitol nu orice limbaj are o reprezentare finit, cu alte cuvinte nu pentru orice limbaj exist o gramatic care s l reprezinte. Dou gramatici G i G' sunt echivalente dac i numai dac L(G) = L(G'). Asupra formelor propoziionale se definete o relaie numit relaie de derivare n modul urmtor. Fie i doua forme propoziionale, dac i numai dac exist w1, w2 i P astfel nct = w1 w2 i = w1 w2. Relaia poate s fie extins obnndu-se derivarea n k pai. i anume a k B dac exist 0, 1, ..., k forme propoziionale astfel nct = 0, i-1 i ,1 i k i k = . Inchiderea tranzitiv a relaiei se noteaz cu + . Inchiderea tranzitiv i reflexiv a relaiei se noteaz cu =*>. S considerm de exemplu gramatica G = ({A,S}, {0,1}, P, S) unde P = {S 1A1, S 0S0, 1A 11A1, A } (cu s-a notat irul vid de simboli). O derivare posibil este:

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

S 0S0 00S00 001A100 0011A1100 00111100

deci 00111100 este o propoziie n L(G). n general L(G) = { w | w T+, S + w}.

Ierarhia Chomsky.
Noam Chomski este lingvist i lucreaza n domeniul limbajelor naturale. Ierarhia care i poarta numele a rezultat dintr-o ncercare a acestuia de a formaliza limbajele naturale. Gramaticile sunt clasificate conform complexitii producilor n urmtoarea ierarhie : gramatici de tip 0 (fr restrictii) - au produciile de forma: cu (N T)* N (N T)* , (N T)* gramatici de tip 1 (dependente de context) - au produciile de forma : A
, , (N T)*, A N, (N T)*

sau de forma
S

n al doilea caz S nu apare n membrul drept al niciunei producii. Se utilizeaz termenul de dependen de context deoarece producia A poate s fie interpretat sub forma - dac simbolul neterminal A apare ntre i atunco poate s fie nlocuit cu . gramatici de tip 2 (independente de context) - au produciile de forma :
A , A N, (N T)*.

Denumirea de independent de context apare n contrast cu gramaticile de tipul 1 (dependente de context) gramatici de tip 3 (regulate la dreapta) au producii de forma:
A aB cu A N , B (N {}) si a T+.

Corespunztor gramaticilor, despre limbajele generate de acestea se poate spune respectiv c sunt regulate, independente de context, dependente de context sau de tipul zero. Se poate arata c un limbaj care poate s fie generat de o gramatic regulat poate s fie generat i de ctre o gramatic independent de context. Un limbaj independent de context poate s fie generat i de o gramatic dependent de context iar un limbaj dependent de context poate s fie generat i de o gramatic de tipul zero. Deoarece cu ct o gramatic este mai restrictiv ea reprezint un mecanism mai simplu, suntem ntotdeauna interesai de cea mai restrictiv gramatic care reprezint un limbaj dat. S considerm cteva exemple:

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

10

a) G1 = ({S},{0,1},{S 0S, S 1S, S }, S). Se observ c G1 este o gramatic regulat care genereaz limbajul {0,1}*. b) G2 = ({S, A},{0,1},{S AS, S , A , A 0, A 1}, S). Se observ c G2 este o gramatic independent de context iar limbajul generat este tot {0,1}*. Rezult deci c un acelai limbaj poate s fie definit de mai multe gramatici diferite eventual chiar de tipuri diferite. c) G3 = ({, T, F},{a, +, *, (, )}, P, ) cu P = { + T, T, T T * F, T F, F (), F a}. S considerm un exemplu de derivare n aceast gramatic : + T T + T F + T a + T a + T * F a + F * F a + a * F a + a * a. Se observ c gramatica G3 este o gramatic independent de context i este o gramatica care descrie limbajul expresiilor aritmetice cu paranteze care se pot forma cu operandul a i cu operatorii + i *. n cele ce urmeaz pentru simplificarea notaiilor dac pentru un neterminal exist mai multe producii : A w1, A w2, ... A wk le vom reprezenta sub o form mai compact: A w1 | w2 | ... | wk. De asemenea pentru specificarea unei gramatici nu vom mai preciza n general dect mulimea produciilor sale, celelalte elemente rezultnd n mod banal din aceasta.

Exerciii
S se construiasc gramaticile care genereaz limbajul: 1. irurilor formate din simboli a i b avnd un numr egal de a i b. 2. {anbn | n 1} 3. {anbmcmdn | n 1, m 1} 4. {anbncmdm | n 1, m 1} 5. irurilor formate cu simboli a i b care nu conin subirul abb 6. irurilor formate cu simboli a i b avnd lungimea divizibil cu 3 7. {aibj | i /= j, i, j > 0} 8. {ambn | n < m sau n > 2m, n, m 1} 9. irurilor formate dintr-un numr par de simboli a i un numr impar de simboli b 10.irurilor formate din simboli a, b i c, pentru care toi simboli a apar nainte de toi simboli b iar toi simboli b apar nainte de toi simboli c 11.{anbncn | n >_ 1} 12.{xcxR |x {a,b}*}, {xxR|x {a,b}*}, {x = xR|x {a,b}*} 13.{xx | x {a,b}*} 14.{anbncn | n 1 } 15.listelor de elemente care pot s nu conin nici un element, respectiv trebuie s conin cel puin un element, construirea listei este asociativ dreapta respectiv stnga (vor rezulta 4 variante)

10

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

11

1.1.1. Verificarea limbajului generat de ctre o gramatic


n toate exemplele considerate pn acum s-a facut "ghicirea" gramaticii care genereaz un limbaj dat sau a limbajului generat de ctre o gramatic dat. Se pune ns problema cum se poate demonstra corectitudinea rezultatului unei astfel de ghiciri. S considerm de exemplu gramatica: G = ({S}, {(,)}, {S (S)S | }, S) Aceast gramatica genereaz toate irurile de paranteze bine nchise (echilibrate). Dorim ns s demonstrm aceast afirmaie. De fapt aici trebuie s demonstrm egalitatea a dou mulimi: mullimea reprezentat de imbajul generat de G i mulimea irurilor de paranteze bine formate. Deci demonstraia presupune demonstarea dublei incluziuni. Adic trebuie s demonstrm c orice ir derivat din S satisface condiia enuntata i apoi trebuie s demonstrm incluziunea n sens invers. Dndu-se un ir de paranteze bine nchise trebuie s aratm c acest ir poate s fie derivat din S. Pentru prima parte a demonstraiei vom utiliza inducia asupra numrului de pai n derivare. Considerm c irul vid care se obine ntr-un pas din S este un ir de paranteze bine nchise. S presupunem c pentru toate derivrile realizate n mai puin de n pai se obin iruri de paranteze bine nchise i s considerm o derivare de exact n pai. O astfel de derivare poate s arate ca :
S (S)S * (x)S * (x)y

unde x i y sunt iruri de terminale derivate din S n mai puin de n pai, adic sunt iruri de paranteze bine nchise. Rezult c irul (x)y este un ir de paranteze bine nchise. Cu alte cuvinte orice ir derivat din S este "corect". S considerm acum i includerea n sens invers. De data asta demonstraia se face prin inducie asupra lungimii irului. Pentru primul pas observm c irul vid este un ir derivabil din S. S presupunem acum ca orice ir cu mai puin de 2n simboli este derivabil din S. S considerm un ir w de paranteze bine nchise avnd lungimea de 2n, cu n mai mare sau egal cu 1. Sigur irul ncepe cu o parantez deschis. Fie (x) cel mai scurt prefix format din paranteze bine nchise. Se observ c w = (x)y, unde x i y sunt iruri de paranteze bine nchise de lungime mai mic dect 2n. n acest caz x i y pot s fie derivate din S. Rezult c exist o derivare:
S (S)S * (x)y

n care pentru obinerea irurilor x i respectiv y s-au utilizat mai puin de 2n pai i deci w este un ir derivabil din S. Desigur o astfel de demonstraie este practic imposibil de realizat pentru un limbaj "adevarat". n general se pot face ns demonstratii "pe poriuni". Exerciii 1. Fie gramatica G : S AA, A AAA, a, A bA, Ab, s se arate ca limbajul L(G) este limbajul tuturor irurilor formate din simboli a avnd un numr par de simboli. 2. Fie gramatica G : S aB | bA, A a | aS | bAA, B b | bS | aBB s se arate ca L(G) este setul tuturor irurilor din {a,b}+ care au un numr egal de apariii pentru a i pentru b.

11

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

12

1.1.2. Transformri asupra gramaticilor independente de context


Din punctul de vedere al procesului de compilare, gramaticile sunt utilizate pentru faza de analiz sintactic, pentru care se utilizeaz gramatici independente de context. Exist o serie de metode de analiza sintactic, bine puse la punct att din punct de vedere teoretic ct i practic. Fiecare dintre aceste metode impune ns o serie de restricii asupra gramaticilor utilizate. n general atunci cnd se construiete o gramatic se pleac de la forma general a structurilor pe care aceasta trebuie s le descrie i nu de la metoda de analiza sintactica ce va fi utilizata. n acest mod se obine o gramatic ce poate s fie "citit" uor de ctre proiectant. Pentru a satisface ns condiiile impuse de ctre metodele de analiza sintactic sau de ctre generarea de cod, se realizeaz transformri asupra gramaticilor. Aceste transformri trebuie s pstreze neschimbat limbajul generat. n cele ce urmeaz vom prezenta cteva transformri tipice asupra gramaticilor independente de context. Pentru a explica semnificaia acestor transformri n contextul analizei sintactice vom prezenta nti noiunea de arbore de derivare. Un arbore de derivare este o reprezentare grafic pentru o secven de derivri (de aplicri ale relaiei ntre formele propoziionale). ntr-un arbore de derivare nu se mai poate identifica ordinea n care s-a facut substituia simbolilor neterminali. Fiecare nod interior arborelui, reprezint un neterminal. Descendenii unui nod etichetat cu un neterminal A sunt etichetati de la stnga la dreapta prin simbolii care formeaz partea dreapt a unei producii care are n partea stnga neterminalul A. Parcurgnd de la stnga la dreapta frunzele unui astfel de arbore se obine o form propoziional. S considerm de exemplu din nou gramatica irurilor de paranteze bine formate:
G = ({S}, {(,)}, {S (S)S | }, S)

Fie urmtoarea secven de derivri: S ( S ) S ( ( S ) S ) S ( () S ) S


( () ( S ) S ) S ( () () S ) S ( () () ) S ( () () ) ( S ) S + ( ()() ) ()

Se obine arborele de derivare:


S //\ \ // \ \ // \ \ (S ) S //\ \ //\ // \ \ (S ) // \ \ | (S ) S | //\ \ // \ \ ( S ) S | | \ S |

Arborele de derivare este construit de ctre analizorul sintactic. Aceasta construcie se poate face pornind de la rdcin aplicnd succesiv producii - n acest caz se spune c analiza sintactic este top-down (descendent). Dar, se poate porni i invers de la irul de atomi lexicali

12

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

13

(frunze) identificndu-se simbolii neterminali din care se poate obine un ir de atomi lexicali. n acest caz se spune c analiza sintactic este de tip bottom-up (ascendent). Deoarece arborele de derivare descrie relaia ierarhica ntre entitile sintactice (neterminale) i atomii lexicali (terminale) se poate asocia o interpretare n termeni de evaluare a entitilor sintactice. Astfel, considernd de exemplu gramatica expresilor aritmetice pentru irul a + a * a se obine arborele derivare :
/|\ / | \ + T | /|\ T / | \ | T * F F | | | F a a | a

n care se poate observa c a fost evideniat faptul c operaia de nmulire este prioritar fa de operaia de adunare (aspect semantic). a. Eliminarea ambiguitii O gramatic care produce mai multi arbori de derivare pentru aceeai propoziie este o gramatic ambigu. Deoarece exist tehnici de analiz sintactic care lucreaz numai cu gramatici neambigue vom ncerca s construim gramatici care genereaz acelai limbaj i care sunt neambigue. S considerm de exemplu urmtoarea gramatic :
instr if expresie then instr | if expresie then instr else instr | alte_instr

S construim arborele de derivare pentru propoziia :

13

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

14

if E1 then if E2 then S1 else S2 instr / /\ \ // \\ // \\ / expr \ \ / / \ then \ if / E1 \ \ ------instr / /\ \ \ \ // \\ \ \ // \\ \ \ / expr \ \ \ \ / / \ then \ \ \ if / E2 \ \ \ \ ------instr \ \ / \ else \ / S1 \ instr -----/ \ / S2 \ ------

Pentru aceast propoziie mai exist ns un arbore de derivare.


instr //\ \ \ \ // \ \ \ \ // \ \ \ \ / expr \ \ \ \ / / \ then \else \ if / E1 \ \ \ ------instr instr / \ / \ / /\ \ / S2 \ / / \ \ -----if / then\ expr instr / \ / \ / E2 \ / S1 \ ------ ------

n toate limbajele de programare care accept construcii de tip if then else se consider cu sens prima derivare n care fiecare clauza else este atribuit instruciunii if cea mai interioar. Rezult deci condiia pe care trebuie s o satisfaca o instruciune if. Instruciunea cuprins ntre then i else trebuie s nu fie o instruciune if sau s fie o intruciune if cu clauza else. Rezult urmtoarea gramatic obinut prin transformarea gramaticii anterioare:
instr if_cu_else| if_fara_else if_cu_else if expresie then if_cu_else else if_cu_else | alte_instr if_fara_else if expresie then instr | if expresie then if_fara_else else if_fara_else

Se observ c aceast gramatic genereaz acelai limbaj cu gramatica accept o derivare unic pentru propoziia :

anterioar dar

14

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

15

if E1 then if E2 then S1 else S2 instr | if_fara_else / /\ \ // \\ // \\ / expr \ \ / / \ then \ if / E1 \ \ ------instr | if_cu_else / /\ \ \ \ // \\ \ \ // \\ \ \ / expr \ \ \ \ / / \ then \ \ \ if / E1 \ \ \ \ ------instr \ \ / \ else \ / S1 \ instr -----/ \ / S2 \ ------

Se numete producie ambigu o producie care are n partea dreapt mai multe apariii ale aceluiai simbol neterminal. Existena unei producii ambigue nu implic faptul c gramatica este ambigu. S considerm gramatica G = ({S, A}, {a, b, c }, {S aAbAc, A a | b}). Se observ c aceast gramatic nu este ambigu, gramatica genernd limbajul {aabac, aabbc, abac, abbc} S considerm de exemplu i gramatica pentru expresii aritmetice:
G = ({}, {a, +, *}, { + | * | a}, )

Gramatica G este o gramatic ambigu (se poate verifica uor utiliznd de exemplu irul a + a * a). n gramatica G nu au fost evideniate relaile de preceden dintre operatori. Aceasta gramatica poate s fie transformata ntr-o gramatica neambigu n care operaia de nmulire este mai prioritar dect cea de adunare n doua moduri:
1. + T | T T T * F | F F a 2. T + | T T F * T | F F a

S considerm irul a * a * a. Pentru cele doua gramatici se obin arborii de derivare respectivi:
| T | T

15

Irina Athanasiu
/|\ / | \ T * F /|\ | / | \ a T * F | | F a | a

10/4/2003
/ / F | a

Limbaje formale si translatoare


|\ | \ * T /|\ / | \ F * T | | a F | a

16

Se observ c primul arbore evideniaz asociativitatea stnga a operatorului * n timp ce al doilea arbore evideniaz asociativitatea dreapta. n funcie de definiia limbajului este de preferat prima variant sau a doua. n cazul general dac pentru un neterminal A exist produciile:
A A B A | 1 | 2 | ... | n , BN, 1, ... n T*

acestea pot s fie inlocuite cu:


A A' B A | A' A' A | 1 | 2 | ... | n

Producia A' A poate s fie eliminata (exist i A A') i se obine:


A A' B A | A'

A' 1 | 2 | ... | n

Dac se construiete arborele de derivare se observ c n acest caz se utilizeaza asociativitatea dreapt. Pentru a se descrie asociativitatea stnga se utilizeaz transformarea:
A A B A' | A' A' 1 | 2 | ... | n.

Trebuie s remarcam ns faptul c exist limbaje pentru care nu se pot construi gramatici neambigue. Un astfel de limbaj se numeste inerent ambiguu. De exemplu limbajul : L = { aibjckdl | i = k sau j = l, i, j, k, l 0} este inerent ambiguu. O gramatic care descrie acest limbaj va trebui probabil s considere c L este de fapt reuniunea a dou limbaje: L = { anbjcndl | n, j, l 0} i L = { aibnckdn | i, n, j, k 0} Un ir de forma apbpcpdp va face parte din ambele limbaje i deci probabil c va avea doi arbori de derivare. Exemplul anterior nu constituie o demonstraie, a crui dificiltate depete ns cadrul textului curent. b. Eliminarea - produciilor Se spune ca o gramatic este - free dac satisface una dintre urmatoarele condiii :

16

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

17

a. Nu exist nici o producie care s aib n partea dreapta irul vid sau b. Exist o singura producie care are n partea dreapta irul vid i anume producia S . Simbolul S nu apare n acest caz n partea dreapt a nici unei producii. Algoritmul de transformare este : Intrare O gramatica G = (N, T, P, S) Iesire O gramatica G' = (N', T, P', S') care satisface condiiile : (i) L(G) = L(G') (i) G' este - free. Descrierea algoritmului este :
i=0 Ni = {A | A P} repeta i=i+1 Ni = { A | A a P, a N*i-1} Ni-1 pna Ni = Ni-1 Ne = Ni dac S Ne atunci N' = N {S'} P' = {S' , S' S} altfel N' = N S' = S P' = pentru fiecare p P executa dac p este de forma : A a0 B1 a1 ... Bk ak, k 0, Bi Ne, 1 i k, aj ((N \ Ne) T)*, 0 j k atunci P' = P' ({A a0 X1 a1 ... Xk ak | Xi {Bi, }} \ {A }) altfel P' = P' {p}

Fie de exemplu gramatica S aSbS | bSaS | . Aplicnd algoritmul anterior se obine : S' S, S aSbS | aSb | abS | ab | bSaS | bSa | baS | ba c. Eliminarea recursivitatii stnga

17

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

18

O gramatic este recursiv stnga dac exist un neterminal A astfel nct exist o derivare A + A pentru (T N)*. O analiz sintactic de tip top-down nu poate s opereze cu o astfel de gramatic, deci este necesar o transformare. S considerm inti cazul cel mai simplu pentru care n gramatic exist producii de forma A A | . Astfel de producii pot s fie nlocuite cu: A A', A' A'| . S considerm de exemplu gramatica expresiilor aritmetice : + T | T, T T * F | F, F () | a Se observ c pentru un ir de forma a + a * a, examinnd numai primul simbol terminal(a) nu este clar cu care dintre produciile pentru trebuie s se nceap derivarea. Aplicnd ideea anterioar se obine : T ', ' +TE' | , T FT', T' *FT' | , F () | a n acest caz derivarea va incepe sigur prin aplicarea produciei TE' i se obine derivarea TE' FT''. n acest moment se vede c pentru F trebuie s se aplice producia F a. Deci se obine + aT''. Urmeaz simbolul terminal + datorit cruia pentru T' se va aplica producia T' , etc. n general dac pentru un neterminal A exist produciile : A A1 |A2 | ... |Am | 1 | 2 | ... | n unde i nu incepe cu A, 1 i n, se pot nlocui aceste producii cu : A 1A' | 2A' | ... | nA' A' 1A' | 2A' | ... | mA'| Aceast construcie elimin recursivitatea stng imediat. S considerm ns gramatica: A1 A2 a | b A2 A3 c | d A3 A1 e | f cu A1 simbolul de start al gramaticii. Se observ c este posibil urmtoarea derivare A1 A2a => A3 ca => A1 eca deci gramatica este recursiv stnga. Se observ c dac am considerat o ordine a simbolilor, toate produciile mai puin ultima, respect regula "un simbol neterminal trece eventual ntr-un alt simbol neterminal cu un numr de ordine mai mare". Existena unei producii care nu respect condiia conduce la apariia recursivitii stnga. Dac gramatica nu permite derivari de tipul A + A (fr cicluri) i nu conine - producii poate s fie transformat n vederea eliminrii recursivitii stnga utiliznd urmtorul algoritm. Intrare. O gramatic fr cicluri i - producii Iesire. O gramatic echivalent fr recursivitate stnga. Descrierea algoritmului este :

18

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

19

Se aranjeaza neterminalele n ordinea A1, ..., An pentru i = 1 pn la n executa pentru j = 1 pn la i - 1 executa inlocuieste fiecare producie de forma Ai Aj cu produciile Ai 1 r | 2 r | ... | k r unde Aj 1|2| ... |k sunt toate produciile pentru Aj elimin recursivitatea stnga ntre produciile Ai

S considerm pasul i. Produciile Ak Al care au mai rmas (pentru care k < i), au l > k. n aceasta iteraie prin variaia lui j se ajunge ca pentru orice producie de forma Ai Am , m i. Dac se elimin recursivitatea direct rmne m > i. S considerm de exemplu din nou gramatica : A1 A2a | b, A2 A2c | A1d | e Considerm pentru neterminale ordinea : A1, A2. Pentru A1 (i = 1) nu exist recursivitate stnga direct deci nu se face nici o modificare. Pentru i = 2, producia A2 A1d se inlocuiete cu A2 A2ad | bd. Rezult deci c A2 A2c | A2ad | bd | e. Eliminnd recursivitatea stnga se obine : A1 A2a | b, A2 bdA2' | eA2', A2' cA2' | adA2' | d. Factorizare stnga Acest tip de transformare este util pentru producerea unei gramatici potrivite pentru analiza sintactic descendent de tip determinist. Ideea este c dac nu este clar care dintre produciile alternative poate s fie aplicat pentru un neterminal se va amna luarea unei decizii pn cnd s-a parcurs suficient din irul de intrare pentru a se putea lua o decizie. S considerm de exemplu produciile : SAbS|A ABcA|B B a | dSd S presupunem c ncercm s construim irul derivrilor pentru a b a c a pornind de la simbolul de start al gramaticii. Din recunoaterea simbolului a la nceputul irului nu se poate nc trage concluzia care dintre cele doua producii corespunztoare neterminalului S trebuie s fie luata n considerare (abia la ntlnirea caracterului b pe irul de intrare se poate face o alegere corect). n general pentru producia A 1 | 2 dac se recunoate la intrare un ir nevid derivat din nu se poate tii dac trebuie aleas prima sau a doua producie. Corespunztor este util transformarea: A A', A' 1 | 2. Algoritmul de factorizare funcionez n modul urmtor. Pentru fiecare neterminal A se caut cel mai lung prefix comun pentru dou sau mai multe dintre produciile corespunztoare neterminalului A. Dac atunci se nlocuiesc produciile de forma A 1 | 2 | ... | n | (unde reprezint alternativele care nu ncep cu ) cu :

19

Irina Athanasiu A A' | A' 1 | 2 | ... | n

10/4/2003

Limbaje formale si translatoare

20

A' este un nou neterminal. Se aplic n mod repetat aceast transformare pn cnd nu mai exist dou alternative pentru un neterminal avnd un prefix comun. Relund exemplul considerat se obine : S AX X bS | A BY Y cA | B a | dSd Deci n analiza irului a b a la ntlnirea simbolului b pentru neterminalul Y se va utiliza producia Y , n acest mod rezult irul de derivari : S AX BYX aYX ... e. Eliminarea simbolilor neterminali neutilizai Un simbol neterminal neutilizat este un simbol care nu poate s apar ntr-o form propoziional (simbol inaccesibil) sau din care nu poate deriva un ir format numai din simboli terminali sau care apare n formele propoziionale numai datorit sau mpreun cu simboli neterminali ce satisfac una dintre condiiile anterioare. Eliminarea simbolilor nefinalizai se face utiliznd urmtorul algoritm : Intrare O gramatic G = (N, T, P, S) Iesire O gramatic G' = (N', T, P', S) care satisface urmtoarele condiii : (i) L(G) = L(G') (i) A N, A + w, w T*. Descrierea algoritmului este :
N0 = i=0 repeta i=i+1 Ni = { A | A P si (Ni-1 T)* } Ni-1 pn Ni = Ni-1 N' = Ni P' P contine numai productiile din P care au n partea stnga simboli din N' si n partea dreapta simboli din N' si T.

Prin inducie asupra numrului de pai se poate demonstra corectitudinea algoritmului. S considerm ca exemplu o gramatic avnd produciile : P = {S A, A a, B b, B a}, se observ c B este un simbol neterminal inaccesibil. Aparent condiia de inaccesibilitate pentru un neterminal const din ne apariia n partea dreapt a unei producii. Dac ns considerm o gramatic avnd produciile: {S A, A a, B cC, C bB} se observ c este necesar o alt condiie. Eliminarea simbolilor inaccesibili se poate face utiliznd urmtorul algoritm.

20

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

21

Intrare O gramatic G = (N, T, P, S) Ieire O gramatic G' = (N', T, P', S) care satisface urmtoarele condiii : (i) L(G) = L(G') (i) A N', w (N T)*, S w i A apare n w Descrierea algoritmului este:
N0 = {S} i=0 repeta i = i + 1; Ni = {A | A apare n partea dreapta a unei productii pentru un neterminal din Ni-1} Ni-1 pn Ni = Ni-1 N' = Ni P' contine numai productii care corespund neterminalelor din N' si care contin n partea dreapta simboli neterminali numai din N'

Prin inducie asupra numrului de pai se poate determina corectitudinea algoritmului. Utiliznd algoritmii pentru eliminarea simbolilor nefinalizai i cel pentru eliminarea simbolilor inaccesibili se obine o gramatic care nu conine simboli neutilizati. Ordinea n care se aplic aceti algoritmi nu este indiferent. S considerm de exemplu gramatica cu producile: S a | A, A AB, B b. Dac se aplic nti algoritmul pentru eliminarea simbolilor nefinalizai, ramn produciile S a i B b. Prin eliminarea simbolilor inaccesibili ramne numai producia S a. Dac ns se aplic nti algoritmul pentru eliminarea simbolilor inaccesibili i apoi cel pentru eliminarea simbolilor nefinalizai vor ramne pn la sfrit ambele producii S a i B b. g. Substituia de nceputuri(corner substitution) Anumite metode de analiz sintactic impun ca partea dreapt a fiecarei producii care nu este irul vid s nceap cu un terminal sau s fie irul vid. S considerm de exemplu gramatica avnd produciile:
lista elem lista | a elem a(numr) | *elem

S nlocuim apariia neterminalului elem n prima producie. Se obine:


lista a(numr) lista | *elem lista | a elem a(numr) | *elem

S realizam i factorizarea produciilor neterminalului lista:

21

Irina Athanasiu
lista aX | *elem lista X (numr) lista | elem a(numr) | *elem

10/4/2003

Limbaje formale si translatoare

22

Se observ ca n acest caz n funcie de simbolul terminal curent se poate decide n mod determinist care este producia urmtoare ce trebuie s fie aplicat pentru derivare (construirea arborelui de derivare). O gramatic independent de context pentru care este indeplinit condiia ca partea dreapt a oricrei producii ncepe cu un terminal sau este irul vid se numete gramatic de tip Q. O form particular de gramatica de tip Q este forma normal Greibach. n acest caz nu exist -producii cu exceptia cel mult a unei -producii corespunztoare simbolului de start al gramaticii. n cazul n care aceasta producie exist simbolul de start al gramaticii nu apare n partea dreapt a nici unei producii. n forma normal Greibach produciile sunt de forma Aa cu a T i N*. S presupunem c o gramatic are produciile: P a1 1 | a2 2 | ... | an n | unde ai T, i j ai aj, 1 i, j n. O procedur care recunoate irurile derivate din P este de forma:
p() { switch (caracter_urmtor) { case a1 : avans(); a1 /* tratare a1 */ case a2 : avans(); a2 ... case an : avans(); an default: /* ? - producie */ } }

Pe baza transformrilor anterioare se poate elabora un algoritm pentru construirea unei gramatici n forma normal Greibach pentru o gramatic independent de context care nu este recursiv stnga. Se definete nti o relaie de ordine asupra neterminalelor unei gramatici. i anume A < B dac exist o producie A B . Considernd aceast relaie se observ c se obine o relaie parial de ordine care poate s fie extinsa la o relaie liniar de ordine. Dac gramatica pentru care se construiete aceast relaie nu este recursiv dreapta atunci produciile celui "mai mare" neterminal ncep sigur cu simboli terminali. Rezult algoritmul: Intrare O gramatic G independent de context care nu este recursiv stnga, nu are cicluri, nu are simboli neutilizai i nu are -producii cu excepia cel mult a unei -producii corespunztoare simbolului de start al gramaticii. n acest ultim caz simbolul de start al gramaticii nu apare n partea dreapt a nici unei producii. Iesire O gramatic G' n forma normal Greibach Descrierea algoritmului este:
Se construieste relaia de ordine asupra N astfel inct N= {A1, A2, ..., An} si A1 < A2 < ... < An. pentru i = n - 1 pn la 1 pas = -1 executa

22

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

23

fiecare productie de forma Ai Aj cu i < j se inlocuieste cu Ai 1 | ... | m unde Aj 1 | ...| m (se observa ca 1, ..., m incep cu terminale) pentru fiecare productie de forma p = A a X1 ... Xk executa pentru i = 1 pn la k executa dac Xi T atunci N = N {Xi'} P = P { Xi' Xi}

P = P \ {p} {A aX1'X2' ... Xk'}

Prin inducie asupra numrului de pai se poate demonstra c algoritmul realizeaz transformarea dorit. De exemplu pentru gramatica expresiilor aritmetice n forma fr producii:
' T T' F T ' +TE' FT' *FT' () | | | | | T, +T, F, *F a

Relaia de ordine liniar poate s fie ' < < T' < T < F. Se pornete de la F, pentru care toate produciile ncep cu un terminal. Rezult modificarea produciilor pentru T:
T () T' | a T' | () | a.

Urmeaz T' care nu necesit transformri. Pentru se obine:


()T'' | a T' ' | ()' | aE' | ()T' | aT' | () | a

De asemenea ' nu se modific. Rezult urmatoarea gramatic n forma normal Greibach:


' T T' F A (EAT'' | a T' ' | (EAE' | aE' | (EAT' | aT' | (EA | a +TE' | +T (EA T' | a T' | (EA | a. *FT' | *F (EA | a )

1.1.3. Construcii dependente de context


Anumite construcii specifice limbajelor de programare de nivel inalt nu pot s fie descrise prin limbaje independente de context. S considerm cteva exemple : 1. Fie limbajul L1 = {wcw| w {0,1}*}. Acest limbaj realizeaz abstractizarea condiiei ca un identificator s fie declarat nainte de a fi utilizat. L1 nu poate s fie generat de o gramatic

23

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

24

independent de context. Din acest motiv condiia ca un identificator s fie definit nainte de a fi utilizat nu pot s fie verificat prin analiz sintactic, deci va fi verificat de ctre analiza semantic. 2. Fie limbajul L2 = {anbmcndm | n > 1, m > 1}. Acest limbaj realizeaz abstractizarea corespondenei ca numr ntre numrul de parametrii cu care au fost declarate procedurile i numrul de parametrii cu care se utilizeaz acestea. Nici acest limbaj nu pot fi descris de o gramatic independent de context. Pe de alt parte limbajul L2' = {anbn | n > 1}, poate s fie descris de gramatica : S a S b | a b. Deci i aici dup o prim recunoatere fcut n analiza sintactic, partea de dependen de context va fi rezolvat de ctre faza de analiz semantic. Observaie n general o gramatic independent de context poate s "numere" doi termeni dar nu trei sau mai muli. Dac pentru recunoaterea unui ir din limbaj se poate utiliza un algoritm care utilizeaz o singur stiv (sau un singur contor) atunci limbajul poate s fie descris de o gramatic independent de context. O gramatica regulata nu poate s "numere" dect pn la o limit finit.

Exerciii
1. Fie gramatica:
A BC | a. B CA | Ab, C AB | cC | b

S se construiasca gramatica echivalenta nerecursiva stnga 2. S se elimine simbolii neutilizai pentru gramatica:
S A | B, A aB | bS | b, B AB | BA, C AS|b

3.

S se construiasc gramatica echivalenta fr -producii pentru gramatica: S ABC, A BB | , B CC | , C AA | b

4.

S se construiasc un algoritm care verific dac pentru o gramatic dat G, L(G) este mulimea vid. S se demonstreze c algoritmul este corect

24

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

25

1.1.4. Propieti ale limbajelor independente de context


Limbajele formale sunt mulimi - putem s aplicm asupra lor operaii caracteristice mulimilor : reuniune, intersecie, diferen dar i operaii specifice cum este de exemplu concatenarea. Dac L1 i L2 sunt dou limbaje, concatenarea lor este un limbaj L = L1L2 astfel nct: L = { w | w = xy, x L1, y L2} O alt operaie specific ce se poate aplica asupra unui limbaj formal L este "Kleen star". Notaia utilizat pentru rezultat este L* i reprezint mulimea irurilor obinute prin concatenarea a zero sau mai multe iruri din L (concatenarea a zero iruri este irul vid, concatenarea unui singur ir este el nsui, etc). Se va utiliza i notaia L+ pentru LL*. Dac aplicnd o operaie asupra orcror doua limbaje independente de context obinem un limbaj independent de context vom spune c mulimea limbajlor independente de context este nchis sub operaia respectiv. Se poate demonstra c mulimea limbajelor independente de context este nchis sub operaiile: reuniune, concatenare i star. S demonstrm de exemplu nchiderea sub operaia de reuniune. Fie doua gramatici G1 = (N1, T1, P1, S1), G2 = (N2, T2, P2, S2). Putem ntotdeauna s presupunem c N1 N2 = eventual prin redenumirea simbolilor neterminali din una dintre gramatici). Gramatica corespunztoare limbajului reuniune a limbajelor generate de ctre cele doua gramatici se poate construi n modul urmtor:
G = (N, T, P, S), N = N1 N2 {S}, T = T1 T2, P = P1 P2 {S S1 | S2}

Pentru a demonstra c limbajul L(G) = L(G1) L(G2) trebuie s demonstrm includerea mulimilor n ambele sensuri. Dac w L(G) nseamn c a fost obinut printr-o derivare ca S S1 * w sau S S1 * w. Deci un ir derivat din S aparine limbajului L(G1) L(G2). Invers dac alegem un ir w L(G1) L(G2) el este obinut dintr-o derivare din S1 sau din S2, deci se poate construi o derivare pentru acest ir i n G. Construcii similare se pot face i pentru operaia de concatenare i pentru operaia Kleen star. De exemplu L(G1)* pentru o gramatica G1 = (N1, T1, P1, S1) poate s fie generat de ctre:
G = (N1, T1, P1 {S1 | S1 S1}, S1)

Clasa limbajelor independente de context nu este inchis la operaiile de intersecie i complementare. S considerm de exemplu limbajele L1 = {anbncm | n,m 0}, L2 = {ambncn | n,m 0}. Limbajul L = L1 L2 este "cunoscut" ca find un limbaj dependent de context. S presupunem acum c pentru un limbaj independent de context generat de ctre gramatica G = (N, T, P, S), limbajul complementar, adica T* - L(G) este ntotdeauna independent de context. n acest caz, fie L un limbaj obinut prin intersecia a dou limbaje independente de context: L1 i L2. Se poate scrie: L = L1 L2 = T* - ((T* - L1) (T* - L2)). Dac mulimea limbajelor independente de context este nchis la operaia de complementare atunci (T* - L1) i (T* - L2) sunt limbaje independente de context i la fel este i reuniunea lor

25

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

26

i la fel va fi i complementarea limbajului obinut prin reuniune. Adic ar rezulta c L1 L2 este un limbaj independent de context ceea ce deja tim c nu este adevarat. Dup cum s-a constatat acelai limbaj poate s fie descris de mai multe gramatici, eventual de tipuri diferite. Este util gsirea unui criteriu prin care s se indice tipul restrictiv al gramaticilor care pot s descrie un limbaj dat. De exemplu s considerm limbajul: { an * n| n > 1 } Se pune problema dac exist o gramatica independent de context care s-l genereze. Urmatorul rezultat ne d un criteriu cu ajutorul cruia putem s demonstrm c o gramatic nu este independent de context. Lema de pompare Fie L un limbaj independent de context. Atunci, exist o constanta k care este caracteristic limbajului astfel nct dac z L i |z| k, atunci z poate s fie scris sub forma z = uvwxy cu vx , |vwx| k , |w| 1 i pentru orice i, uviwxiy L. S utilizm rezultatul anterior pentru a studia limbajul: L= { an * n| n > 1 }

s presupunem c L este independent de context. Inseamn c exist un numr k (asociat limbajului) astfel nct dac n * n k atunci an x n = uvwxy astfel nct v i x nu sunt amndou iruri vide i |vwx| k. S presupunem ca n este chiar k ( k * k > k). Rezult ca uv2wx2yL. Deoarece |vwx| k rezult 1 |vx| < k deci lungimea irului iniial k x k < |uv2wx2y| < k x k + k. Dupa k x k urmtorul ptrat perfect este (k + 1) x (k + 1) care este mai mare deci k x k + k, adic |uv2wx2y| nu poate s fie un ptrat perfect, deci L nu poate s fie generat de o gramatic independent de context. Exerciii 1. S se arate c limbajul { anbncn | n > 1 } nu este independent de context 2. S se arate c limbajul { anbncj | n > 1, j < n } nu este independent de context

1.2. Mulimi regulate, expresii regulate.


Fie T un alfabet finit. Se numete mulime regulat asupra alfabetului T mulimea construit recursiv n modul urmtor: 1. este o mulime regulat asupra alfabetului T; 2. Dac a T atunci {a} este o mulime regulat asupra alfabetului T; 3. Dac P i Q sunt mulimi regulate atunci PQ, PQ, P* sunt mulimi regulate asupra alfabetului T. 4. Nimic altceva nu este o mulime regulat. Se observ deci c o submulime a mulimii T* este o mulime regulat asupra alfabetului T dac i numai dac este mulimea vida, este o mulime care conine un singur simbol din T sau poate s fie obinut din aceste dou tipuri de mulimi utiliznd operaiile de reuniune (P Q), concatenare (PQ) sau nchidere P*. Descrierea mulimiilor regulate se poate face cu ajutorul expresiilor regulate. O expresie regulat este la rndul ei definit recursiv n modul urmtor (prin analogie cu definiia mulimiilor regulate) :

26

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

27

1. este o expresie regulata care descrie mulimea ; 2. a T este o expresie regulat care descrie mulimea {a}; 3. dac p,q sunt expresii regulate care descriu mulimile P i Q atunci : a. (p + q) sau (p | q) este o expresie regulat care descrie mulimea P Q; b. (pq) este o expresie regulat care descrie mulimea PQ; c. (p)* este o expresie regulat care descrie mulimea P*. 4. nimic altceva nu este o expresie regulat. De exemplu expresia (0 | 1)* reprezint mulimea {0,1}*, expresia regulat : (00 | 11)*((01 | 10)(00 | 11)*(01 | 10)(00 | 11)*)* reprezint mulimea care conine toate irurile formate din 0 i 1 i care conin un numr par din fiecare simbol. n particular pp* este notat cu p+. ntre operatorii utilizai n descrierea mulimilor regulate exist o serie de relaii de preceden. Cea mai prioritar operaie este operaia de nchidere (notat cu *), urmeaz operaia de concatenare, cel mai puin prioritar este operaia + (|). De exemplu, expresia regulat (0 | (1(0)*)) poate s fie scrisa i sub forma 0 | 10*. Expresiile regulate au o serie de proprietai. Fie , , , expresii regulate. Spunem ca = dac i numai dac i descriu aceleai mulimi regulate. Sunt adevrate urmtoarele proprieti : 1. | = | 3. () = () 5. ( | ) = | 7. * = | * 9. | = 2. | ( |) = ( | ) | 4. ( |) = | 6. ? = ? = 8. (*)* = *

Utiliznd expresii regulate se pot construi i rezolva ecuaii avnd ca soluii expresii regulate. S considerm de exemplu ecuaia:
X = aX + b

unde a,b i X sunt expresii regulate. Se poate verifica uor c X = a*b este o soluie a acestei ecuaii. Dac a este o expresie regulat care poate s genereze irul vid atunci soluia prezentat anterior nu este unic. S nlocuim n ecuaie pe X cu expresia regulat:
a*(b + t)

Se obine:
a*(b + t) = a[a*(b + t)] + b = = a+ b + a+ t + b = = (a+ + )b + a+t = a*b + a*t = a*(b + t)

Se numete punct fix al unei ecuaii cea mai mic soluie a ecuaiei respective. Propoziie Dac G este o gramatic regulat atunci L(G) este o mulime regulata. Demonstraia acestei teoreme se face prin construcie. Nu vom face demonstraia dar vom considera nite exemple, de construcii. Fie gramatica G = ({A, B, C}, {0,1}, P,A) cu P = {A

27

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

28

1A | 0B, B 0B | 1C, C 0B| 1A| }. Se cere s se construiasc expresia regulat care genereaz acelai limbaj ca i G. Se pot scrie urmtoarele ecuaii: A = 1A + 0B B = 0B + 1C C = 0B + 1A + Din prima ecuaie se obine: A = 1*0B Din a doua ecuaie se obine: B = 0*1C Inlocuind n A se obine: A = 1*00*1C = 1*0+1C Inlocuind n a treia ecuaie se obine : C = 0+1C + 1+0+1C + C = ( + 1+)0+1C + = 1*0+1C C = (1*0+1)* Rezult: A = 1*0+1 (1*0+1)* A = (1*0+1)+ Mulimea regulat descrie irurile de 0 i 1 care se termin cu subirul 01. Evident o expresie mai simpl pentru descrierea aceluiai limbaj este: (0 | 1)*01 Se observ c se poate considera c limbajul se obine prin concatenarea a doua limbaje unul descris de expresia (0 | 1)* i cellalt descris de expresia 01. Rezult urmtoarea gramatic: S AB A 0A | 1A | B 01 Se observ c gramatica obinut nu este regulat. S transformm aceast gramatic prin substituie de nceputuri: S 0AB | 1AB | B A 0A | 1A | B 01 Se obine:

28

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

29

S 0S | 1S |01 Utiliznd factorizarea: S 0X | 1S X S | 1 Din nou prin nlocuire de nceputuri se obine: X 0X | 1S |1 Aplicnd factorizarea: X 0X | 1Y YS| Rezult gramatica descris de produciile: S 0X | 1S X 0X | 1Y Y 0X | 1S | . Se observ c s-a ajuns la aceai gramatic cu cea iniial ( desigur dac redenumim neterminalele). Expresiile regulate reprezint o metod alternativ generativ pentru definirea limbajelor regulate. Limbajele definite de gramatici regulate sunt utilizate la nivelul analizei lexicale, n majoritatea limbajelor de programare modul de scriere al numelor i al identificatorilor pot s fie descrise de gramatici respectiv de expresii regulate. Construirea expresiilor regulate corespunztoare atomilor lexicali reprezint prima etapa n proiectarea unui analizor lexical.

1.3. Acceptoare
Un acceptor este un dispozitiv format dintr-o band de intrare, o unitate de control i o memorie auxiliar.
+--------------|a0|a1|...|an| +--------------\ cap de citire \ +---------+ | unitate | | de | | control | +---------+ | +-----------+ | memorie | | auxiliara | +-----------+

29

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

30

Banda de intrare este formata din elemente n care se inscriu simbolii din irul de intrare. La un moment dat capul de citire este fixat pe un simbol. Funcionarea dispozitivului este dat de aciunile acestuia. ntr-o aciune capul de citire se poate deplasa la stnga sau la dreapta sau poate s rmn nemicat. n cadrul unei aciuni unitatea de control are acces la informaia din memoria auxiliar pe care o poate modifica. Se observ ca acest model este foarte general. Utiliznd diferite restricii asupra benzii de intrare, organizrii i accesului la memoria auxiliar se obin diferite cazuri particulare de acceptoare. O aciune a acceptorului este formata din : deplasarea capului de citire la stnga sau la dreapta sau meninerea capului de citire pe aceeai poziie i / sau; memorarea unei informaii n memoria auxiliar i / sau; modificarea strii unitaii de control.

Comportarea unui acceptor poate s fie descris n funcie de configuraiile acestuia. O configuraie este format din urmtoarele informaii : starea unitii de control; coninutul benzii de intrare i poziia capului de citire; coninutul memoriei.

Rezult c o aciune a acceptorului poate s fie precizat prin configuraia iniial (nainte de aciune) i cea final (dup execuia aciunii). Dac pentru o configuraie dat sunt posibile mai multe aciuni atunci spunem c acceptorul este nedeterminist altfel este determinist. Un acceptor are o configuraie iniial n care unitatea de control este ntr-o stare iniial, capul de citire este fixat pe simbolul cel mai din stnga al irului de intrare iar memoria are un coninut iniial specific. Acceptorul are o configuraie final pentru care capul de citire este situat pe simbolul cel mai din dreapta de pe banda de intrare. Se spune c dispozitivul a acceptat un ir de intrare w dac pornind din configuraia iniial ajunge n configuraia finala. Eventual, notiunea de acceptare poate s fie condiionata i de ajungerea ntr-o anumit stare a unitii de control sau de un anumit coninut al memoriei auxiliare. Evident dac acceptorul este nedeterminist dintr-o configuraie iniial pot avea loc mai multe evoluii. Dac exist ntre acestea una pentru care se ajunge la o configuraie final atunci se spune c dispozitivul a acceptat irul de intrare. Limbajul definit de ctre un acceptor este format din mulimea irurilor acceptate de ctre acesta. Pentru fiecare tip de gramatica din ierarhia Chomsky exist o clasa de acceptoare care definesc aceai clas de limbaje. Dintre acestea cele mai cunoscute (utilizate pentru implementarea compilatoarelor) sunt automatele finite care sunt acceptoare pentru limbaje regulate i automatele cu stiv (push-down), care sunt acceptoare pentru limbajele independente de context. Automatele finite sunt acceptoare fr memorie auxiliar iar automatele cu stiv sunt acceptoare pentru care accesul la memoria auxiliar se face conform unui mecanism de tip stiv.

1.3.1. Automate finite


Un automat finit este un obiect matematic AF = (Q, T, m, s0, F) unde :

30

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

31

Q este mulimea finit a strilor; T este o mulime finit numit alfabet de intrare; m : Q x (T {}) P(Q) este funcia parial a strii urmtoare; s0 Q este o stare numit stare de start; F Q este o mulime de stri numit mulimea strilor finale (de acceptare).

Dac pentru q Q, a T m(q,a) este definit, atunci m(q,a) se numete tranziie, dac a = atunci m(q,a) se numeste -tranziie. Se observ ca pentru o combinaie stare(q Q), intrare(a T) pot s corespund mai multe stri urmtoare, deci aa cum a fost definit, automatul este nedeterminist (AFN). Pentru reprezentarea unui automat finit se pot utiliza dou moduri de reprezentare, printr-o tabela de tranziie sau printr-un graf. S considerm de exemplu automatul care accepta limbajul definit de expresia (a | b)* abb. Poate s fie descris sub forma urmtoarei tabele : simbol de intrare stare 0 1 2 3 a {0, 1} b {0} {2} {3} +

Se observ c n fiecare intrare este specificat mulimea strilor urmtoare n care se trece pentru starea i simbolul corespunztor intrrii respective. Acelai automat finit poate s fie descris de urmtorul graf de tranziie :
a --\/ +---+ +---+ +---+ +---+ start | | a | | b | | b |+-+| -------->| 0 |-->| 1 |-->| 2 |-->||3|| | | | | | | |+-+| +---+ +---+ +---+ +---+ /\ --b

Se observ c pentru fiecare stare exist cte un nod, ntre dou noduri exist un arc etichetat cu un simbol de intrare dac i numai dac se poate trece din starea reprezentat de primul nod n starea reprezentat de al doilea nod la aplicarea la intrare a simbolului cu care este etichetat arcul. De remarcat modul n care a fost specificat starea final. Se spune c un automat finit accept un ir de intrare dac exist o cale n graful de tranziie ntre nodul care reprezint starea de start i un nod care reprezint o stare final, astfel nct irul simbolilor care eticheteaza arcele care formeaz aceast cale este irul de intrare. De exemplu irul aabb este acceptat de automatul descris anterior, care va executa urmtoarele micri: a a b b 0 0 1 2 3 Se observa c pentru acelai ir de intrare exist i alte secvene de intrri care ns nu duc ntr-o stare de acceptare:

31

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

32

a a b b 00000 Un caz particular al automatelor finite este dat de automatele finite deterministe (AFD). n cazul automatelor finite deterministe definiia funciei strii urmtoare se modific: m : S x T S.

Se observ c sunt satisfcute urmtoarele restricii: 1. nu exist -tranzitii; 2. pentru (q, a) Q x T este definit cel mult o tranziie. Se observ ca n acest caz, pentru un ir de intrare dat, n graful de tranziie exist cel mult o cale care pornete din starea de start i duce ntr-o stare de acceptare.

1.3.1.1. Construcia unui automat finit nedeterminist care accept limbajul descris de o expresie regulat dat
Algoritmul pe care l vom prezenta utilizeaz direct structurile din definiia expresiilor regulate. Intrare O expresie regulat r asupra unui alfabet T Iesire Un automat finit nedeterminist (N) care accept limbajul L(r). Pentru construirea automatului se identific n structura expresiei r structurile care n mod recursiv compun expresia i se construiesc automatele finite nedeterministe (AFN) elementare corespunztoare. 1. Pentru expresia , automatul care accept limbajul
+---+ +-----+ start | | |+---+| ------| i |------>|| f || | | |+---+| +---+ +-----+

corespunztor este :

2. Pentru expresia a, automatul care accept limbajul


+---+ +-----+ start | | a |+---+| -------->| i |---->|| f || | | |+---+| +---+ +-----+

corespunztor este :

3. Fie dou expresii regulate r,t pentru care s-au construit automatele finite nedeterministe corespunztoare N(r) i N(t). a. pentru expresia regulat r|t limbajul corespunztor este acceptat de :

32

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

33

33

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

34

------------------------| +---+ +-----+ | | | | N(r) |+---+| | --------->| |-- >|| ||---/ | | | |+---+| | \ / | +---+ +-----+ | \ +---+ / | | \ +-----+ | |/ ------------------------\|+---+| ->| i | || f || | |\ ------------------------/|+---+| +---+ \ | | / +-----+ \ | +---+ +-----+ | / \ | | | N(t) |+---+| | / ---------->| |-- >|| ||---/ | | | |+---+| | | +---+ +-----+ | | | -------------------------

b. pentru expresia regulat rt limbajul corespunztor este acceptat de :


---------------------------| | --------------+----------| | +---+ | +---+ | +-----+ | | | | N(r) | | | | N(t)|+---+| | --------->| i |--- -+> | |---- >|| f ||---| | | | | | | |+---+| | | +---+ | +---+ | +-----+ | | | | | --------------+----------| | | ----------------------------

Se observ ca n acest caz starea final a automatului corespunztor expresiei r coincide cu starea iniial a automatului corespunztor expresiei t. c. pentru expresia regulata r* limbajul corespunztor este acceptat de :
+-<------------+ | | -----|--------------|----+---+ | +---+ +---+ | +-----+ | | | | | N(r) | | | |+---+| --->| i |---------> | |--- --> | |------>|| f || | | | | | | | | |+---+| +---+ | +---+ +---+ | +-----+ | | | /\ | -------------------------| | | +---------------------------------------------+

d. pentru expresia (r) limbajul corespunztor este acceptat de automatul care accepta N(r).

34

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

35

Se observ c pentru fiecare AFN - elementar se adaug cel mult o stare iniial i o stare final. Corespunztor pentru o expresie regulat dat automatul va avea un numr de stri egal cu maxim dublul numrului de simboli de intrare care apar n expresie. Compunerea acestor automate elementare va produce evident un automat care recunoate limbajul generat de expresie. De exemplu pentru expresia regulata : (a|b)*abb se obine : pentru fiecare a din expresie :
+---+ +-----+ | | a |+---+| ------> | i |----> || f || | | |+---+| +---+ +-----+

pentru fiecare b din expresie :


+---+ +-----+ | | b |+---+| ------> | i |----> || f || | | |+---+| +---+ +-----+

pentru a | b :
+---+ +-----+ | | a |+---+| --------> | |---->|| ||---/ | | |+---+| \ / +---+ +-----+ \ +---+ / \ +-----+ | |/ \|+---+| ->| i | || f || | |\ /|+---+| +---+ \ / +-----+ \ +---+ +-----+ / \ | | b |+---+| / ---------->| |----> || ||---/ | | |+---+| +---+ +-----+

n final se obine :

---------------+ / | / +-+ +-+ | / | |a | | |

35

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

36

/ / >|2|->|3|\ | / / || || \| +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ | | | |/ | | | |a | |b | |b |--| > |0|->|1| |6|->|7|->|8|->|9|->|10| | | | |\ /| | | | | | | | |--| +-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ | |b | | / /\ \ \ > |4|->|5|/ / \ || || / \ +-+ +-+ / \ / --------------------

1.3.1.2. Conversia unui automat finit nedeterminist (AFN) ntr-un automat finit determinist(AFD)
Din exemplele anterioare s-a observat c un acelai limbaj reprezentat de expresia regulat (a | b)* abb poate s fie recunoscut de dou automate diferite - unul nedeterminist i unul determinist. Propoziie Pentru orice automat finit nedeterminist exist un automat finit determinist care accept acelai limbaj. Avnd n vedere aceast echivalen ntre cele dou automate se pune problema, cum se poate construi un automat determinist echivalent unui automat nedeterminist dat. n cele ce urmeaz vom considera c automatul finit nedeterminist a fost construit pornind de la o expresie regulat pe baza construciei prezentate n capitolul anterior. Algoritmul care construiete automatul determinist utilizeaz o metod de construire a submulimiilor unei mulimi date. Diferena ntre automatele deterministe i cele nedeterministe este dat de cardinalitatea funciei m. Automatul determinist se va construi calculnd n mod recursiv strile acestuia, simulnd n paralel toate evoluiile posibile pe care le poate parcurge automatul nedeterminist. Starea iniial a automatului finit determinist va corespunde mulimii strilor din automatul nedeterminist n care se poate ajunge pornind din starea iniiala s0 i utiliznd numai -tranzitii. Orice stare s' a automatului determinist corespunde unei submulimi Q' Q a automatului nedeterminist. Pentru aceasta stare i un simbol de intrare a T, m(s',a) = {s Q | ( q Q')(s = m(q,a))}. Rezult deci c n funcionarea AFD care simuleaz de fapt funcionarea AFN se urmresc simultan toate "cile" pe care poate evolua automatul finit nedeterminist. Algoritmul care construiete automatul finit determinist echivalent cu un automat nedeterminist dat utilizeaz dou funcii : -inchidere i move. Funcia -inchidere : P(Q) P(Q) determin pentru fiecare mulime Q' Q setul strilor n care se poate ajunge datorit -tranziiilor. Considernd o stare q a automatului finit determinist (AFD), aceasta reprezint de fapt o submulime Q' Q a automatului nedeterminist. Notm cu -nchidere(q) = -nchidere({s}) sQ' 36

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

37

unde dac s S este o stare care nu are -tranziii atunci: -nchidere({s}) = {s} altfel -nchidere({s}) = -nchidere({s'}) s' m(s,) Construcia funciei -inchidere pentru o mulime Q' se poate face utiliznd urmtorul algoritm : A = Q', B = ct timp A \ B execut fie t A \ B B = B {t} pentru fiecare u Q astfel nct m(t,) = u executa A = A {u} -nchidere(Q') = A Funcia move : P(Q) x T P(Q) este utilizat pentru construcia strii urmtoare a automatului determinist. Astfel pentru o stare q a automatului determinist, cruia i corespunde o mulime Q' Q, i o intrare a T, move(q,a) = m(s,a) sQ' Construcia automatului determinist se face prin construcia unei tabele de tranziii tranz_AFD i a unei mulimi de stri stari_AFD. stari_AFD = {-inchidere({s0})} A= ct timp stari_AFD \ A executa fie t stari_AFD \ A A = A {t} pentru fiecare a T executa B = -inchidere(move(t,a)) stari_AFD = stari_AFD {B} tranz_AFD[t,a] = B

Fie automatul nedeterminist :


---------------+ / |

37

Irina Athanasiu
/

10/4/2003

Limbaje formale si translatoare

38

+-+ +-+ | / | |a | | | / / >|2|->|3|\ | / / || || \| +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ | | | |/ | | | |a | |b | |b |--| > |0|->|1| |6|->|7|->|8|->|9|->|10| | | | |\ /| | | | | | | | |--| +-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ | |b | | / /\ \ > |4|->|5|/ / \ || || / \ +-+ +-+ / \ / --------------------

Se observ c -inchidere(0) = {0, 1, 2, 4, 7}, -inchidere(move({0,1,2,4,7}),a)) = -inchidere({3,8}) = {1,2,3,4,6,7,8}. Dac q1 = {0,1,2,4,7}, q2 = {1,2,3,4,6,7,8} atunci tran_AFD(q1,a) = q2. Continund se obine urmtoarea tabel de tranziie :
stare | intrare | multime corespunzatoare AFN |a |b | -----------+----+----+-------------------------------------q1 | q2 | q3 | {0,1,2,4,7} -inchidere({0}) -----------+----+----+-------------------------------------q2 | q2 | q4 | {1,2,3,4,6,7,8} -inchidere({3,8}) -----------+----+----+-------------------------------------q3 | q2 | q3 | {1,2,4,5,6,7} -inchidere({5}) -----------+----+----+-------------------------------------q4 | q2 | q5 | {1,2,4,5,6,7,9} -inchidere({5,9}) -----------+----+----+-------------------------------------q5 | q2 | q3 | {1,2,4,5,6,7,10} -inchidere({5,10}) ------------------------------------------------------------

Graful automatului finit determinist care a rezultat este :

b --\/ +---+ | | b b >| q3|<---------------------+ / +-| | | +---+ /a | +---+ |

38

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

39

start | |/ | +---+ +---+ +------+ ------>| q1| a \/| | b | |b |+----+| | |---> | q2|---->| q4|----->|| q5 || +---+ | | | | |+----+| +---+ +---+ +------+ /\ || a | | -- |+-<--------+ | a| | | a | +--<--------------------+

Se observ c s-a obinut un automat cu 5 stri fa de 4 stri ct avea automatul finit determinist cu care s-au exemplificat automatele finite deterministe. Deci algoritmul utilizat nu produce neaprat o soluie optim.

1.3.1.3. Construcia unui automat finit determinist care accept limbajul descris de o expresie regulat dat
O expresie regulat poate s fie reprezentat sub forma unui arbore (sintactic). De exemplu pentru expresia regulata (a|b)*abb rezult arborele:
. /\ / \ . b /\ / \ . b /\ / \ * a | /\ / \ a b

Se observ c n nodurile interioare apar operatori iar frunzele sunt reprezentate de ctre simbolii de intrare. Exist trei operatori (|, *, .). Pentru a simplifica construciile considerm pentru orice expresie regulata i un simbol de sfrit pe care l vom nota cu # astfel nct orice expresie regulata r va fi reprezentat de r#. Relund pentru expresia anterioar va rezulta graful:

. /\ / \ . # /\ / \ 6 . b /\

39

Irina Athanasiu / \ 5 . b /\ / \ 4 * a | /\ 3 / \ a b 1 2

10/4/2003

Limbaje formale si translatoare

40

Vom ataa fiecrei frunze un cod unic, de exemplu acest cod poate s fie reprezentat de poziia simbolului respectiv n expresia regulat. Utiliznd aceste coduri se construiesc patru funcii: nullable, firstpos, lastpos, followpos. Primele 3 funcii sunt definite asupra nodurilor din arborele care descrie expresia regulat. Funcia nullable este o funcie logic care are valoarea adevrat dac i numai dac subarborele corespunztor nodului respectiv reprezint o expresie regulat care poate s genereze irul vid. Astfel funcia nullable aplicat subarborelui: | /\ a b are valoarea fals n schimb aplicat asupra subarborelui: * | a are valoarea adevarat. Funcia firstpos aplicat unui subarbore are ca valoare setul codurilor frunzelor corespunztoare poziiilor de nceput pentru subirurile care pot s fie generate de ctre expresia regulat corespunztoare subarborelui respectiv. De exemplu pentru nodul rdcin al subarborelui :

40

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

41

x . /\ / \ * a | /\ 3 / \ a b 1 2

(a | b)* a 1 2 3 firstpos(x) = {1,2,3} lastpos(x) = {3}

Funcia lastpos aplicat unui subarbore are ca valoare setul codurilor frunzelor corespunztoare poziiei de sfrit pentru subirurile care pot s fie generate de ctre expresia regulat corespunztoare subarborelui respectiv. Funcia followpos este definit asupra mulimii codurilor frunzelor. Dac i este un cod atunci followpos(i) este mulimea codurilor j care satisfac urmtoarea condiie. Din expresia regulat corespunztoare arborelui se poate genera un ir care s conin subirul cd, c, d T, astfel nct i este codul corespunztor frunzei datorit creia a aprut simbolul c iar j este codul corespunztor frunzei datorit creia a aprut simbolul d. Altfel spus dac se consider irurile obinute din cuvintele din L(r) (limbajul generat de expresia regulat) prin nlocuirea simbolilor din T cu codurile asociate frunzelor din graf care le genereaz, followpos(i) conine toate codurile care pot s apar imediat dup i n aceste iruri. De exemplu followpos(1) = {1,2,3}. Pentru a calcula followpos trebuie s se calculeze funciile firstpos i lastpos care la rndul lor necesit calculul funciei nullable. Regulile pentru calculul funciilor nullable, firstpos i lastpos sunt urmtoarele : forma nod n n este o frunza cu eticheta n este o frunza cu eticheta avnd codul i
n | /\ / \ c1 c2 . /\ / \ c1 c2

nullable(n) adevarat fals

firstpos(n) {i}

lastpos(n) {i}

nullable(c1) sau nullable(c2) nullable(c1) si nullable(c2)

firstpos(c1) firstpos(c2) dac nullable(c1) atunci firstpos(c1) firstpos(c2) altfel firstpos(c1) firstpos(c)

lastpos(c1)

lastpos(c2)

* | c

adevarat

dac nullable(c2) atunci lastpos(c1) lastpos(c2) altfel lastpos(c2) lastpos(c)

Pentru a calcula followpos(i) care indic ce coduri pot s urmeze dupa codul i conform arborelui se utilizeaz dou reguli :

41

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

42

1. dac n este un nod corespunztor operatorului de concatenare cu subarborii c1 i c2 (respectiv stnga dreapta) atunci dac i este un cod din lastpos(c1) toate codurile din firstpos(c2) sunt n mulimea followpos(i). 2. dac n este un nod corespunztor operatorului *, i i este un cod din lastpos(n) atunci toate codurile din firstpos(n) sunt n mulimea followpos(i). Pentru arborele anterior valorile funciilor firstpos i respectiv dreapta fiecrui nod.
{1,2,3} .{6} /\ / \ / \ {1,2,3} .{5} {6}#{6} /\ 6 / \ / \ {1,2,3} .{4} {5}b{5} /\ 5 / \ / \ {1,2,3} .{3} {4}b{4} /\ 4 / \ / \ {1,2} *{1,2} {3}a{3} | 3 {1,2} | {1,2} /\ / \ / \ {1} a{1} {2}b{2} 1 2

lastpos sunt reprezentate n stnga

Singurul nod pentru care funcia nullable are valoarea adevrat este nodul etichetat cu *. Pe baza acestor valori s calculm followpos(1). n followpos(1) vor apare codurile din firstpos pentru nodul etichetat cu * i codurile din firstpos pentru subarborele dreapta corespunztor operatorului de concatenare (followpos(1) = followpos(2) = {1,2,3}. Rezult urmtoarele valori : nod 1 2 3 4 5 6 followpos {1,2,3} {1,2,3} {4} {5} {6} -

Pornind de la aceste valori se poate construi un graf n care ntre dou noduri i i j exist un arc dac j followpos(i).
---

42

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

43

\/ +---+ +-> | | | | 1 |\ +---+ | +-| | \| | | | +---+ | 3 |-> | | +---+ | | | | | | /+---+ | +>| 2 |/ +----| | +---+ /\ --

+---+ | | | 4 |-> | | +---+

+---+ | | | 5 |-> | | +---+

+-----+ |+---+| || 6 || |+---+| +-----+

Pe baza unui astfel de graf se poate obine un automat finit nedeterminist fr -tranzitii, etichetnd arcele n modul urmtor. Dac ntre nodul i i nodul j exist un arc acesta va fi etichetat cu simbolul care are codul j. Fiecare stare a automatului corespunde unui nod din graf. Automatul are ca stri iniiale strile din firstpos pentru nodul rdcin. Strile finale sunt strile asociate cu simbolul #. Automatul care a rezultat, avnd mai multe stari iniiale nu se ncadreaz de fapt n definiia pe care am dat-o pentru un automat finit. Dac ns mai adaugm o stare suplimentar care s reprezinte unica stare iniial din care pe baza unor tranziii ajungem ntr-una dintre strile automatului obinut, se vede c ne ncadrm n definiia considerat
a --\/ +---+ +-> | | a | | 1 |\ +---+ | +-| | \| | b a |b | +---+ | 3 |-> | | +---+ | | | | | | /+---+ | +>| 2 |/ a +----| | +---+ /\ -b

+---+ +---+ +-----+ | | b | | # |+---+| | 4 |->| 5 |->|| 6 || | | | | |+---+| +---+ +---+ +-----+

Mai interesant ns este faptul c funcia followpos poate s fie utilizat pentru construirea unui automat determinist utiliznd un algoritm similar celui pentru construirea submulimilor.
stari_AFD = { first_pos(radacina) } # multime de multimi de coduri A= cat timp stari_AFD \ A executa fie t stari_AFD \ A # multime de coduri A = A {t} pentru fiecare a T executa X = { followpos(p) | r(p) = a} pt daca X atunci stari_AFD = stari_AFD {X}

43

Irina Athanasiu

10/4/2003
tranz_AFD(t,a) = X

Limbaje formale si translatoare

44

n algoritm firstpos(rdcina) este valoarea funciei firstpos aplicat nodului rdcin, r(c) este simbolul de intrare care n expresia regulata reprezentat de arbore are codul c. Se observ ca firstpos(rdcina) corespunde cu -inchidere(s0) iar followpos(p) reprezint -inchidere(move(...)). Aplicnd acest algoritm i rezultatele anterioare se obine automatul finit determinist reprezentat de urmtorul graf :
b b ---------<---------------------+ \/ / | (a | b)* a b b # +---+ / | 1 2 3456 start | 1,|/ +---+ +---+ +------+ | | | 1,| | 1,| |+----+| ----> | 2,| a | 2,| b | 2,| b ||1,2,|| | 3 |--->| 3,|---->| 3,|---->||3,6 || +---+ |4| |5| |+----+| +---+ +---+ +------+ /\ || a | | -- |+-<--------+ | a| | | a | +--<---------------------+

Fie q1 = firstpos(rdcina) = {1,2,3}. Se observ c r(1) = r(3) = a, r(2) = r(4) = r(5) = b. Pentru q1 i a se obine q2 = followpos(1) followpos(3) = {1,2,3,4}, deci tranz_AFD(q1,a) = q2. Pentru q2 i b, followpos(2) = {1,2,3} = q1 i tranz_AFD(q1,b) = q1, etc. Nici aceasta construcie nu garanteaz faptul c automatul obinut este minim.

44

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

45

1.3.1.4. Simularea unui automat finit determinist


Construim un algoritm care urmeaz s rspund la ntrebarea - dndu-se un automat finit determinist D i un ir, este irul acceptat de ctre automat ? Intrare un AFD (D) i un ir de intrare x. irul se termin cu un simbol special eof. Automatul D are o stare iniial s0 i un set de stri de acceptare (finale) F. Ieire Raspuns "DA" dac D accept irul x, respectiv "NU" dac D nu accept irul x. Algoritmul utilizeaz funciile move (care determin starea urmtoare pentru o stare i un simbol de intrare dat) i caracterul_urmtor (care obine caracterul urmtor din irul de intrare).
s = s0 c = caracterul_urmtor cat timp c eof executa s = move(s,c) c = caracterul_urmtor daca s F atunci rezultat "DA" altfel rezultat "NU"

Dac aplicm acest algoritm pentru automatul :


b -------------b / \ --/ \ \/ V \ +---+ +---+ +---+ +---+ start | | a | | b | | b |+-+| ------> | 0 |>| 1 |> | 2 |> ||3|| | | | | | | |+-+| +---+ +---+ +---+ +---+ | | /\ -- | | | | a | +-----+ | | a | +---------------+ a

care accepta limbajul (a | b)* abb, pentru irul ababb, se observ c va parcurge secvena de stri 012123.

45

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

46

1.3.1.5. Simularea unui automat finit nedeterminist


Prezentm n continuare un algoritm pentru simularea unui automat finit nedeterminist. Algoritmul citete un ir de intrare i verific dac automatul l accepta sau nu. Se consider c automatul a fost construit pornind de la expresia regulat utiliznd prima construcie. n consecin automatul va satisface urmtoarele proprietai : 1. are cel mult de dou ori mai multe stri fa de numrul de simboli i operatori care apar n expresia regulat; 2. are o singur stare de start i o singur stare de acceptare. Dintr-o stare de acceptare nu pleac nici o tranziie; 3. din fiecare stare pleac fie o tranziie pentru un simbol din alfabetul de intrare T, fie o tranziie sau doua -tranziii. Intrare un AFN (N) i un ir de intrare x. irul se termin cu un simbol special eof. Automatul N are o stare iniial s0 i o mulime de stari de acceptare (finale) F. Ieire. Rspuns "DA" dac N accept x, respectiv "NU" dac N nu accept x. Algoritmul de simulare se aseamn cu cel utilizat pentru construcia unui automat finit determinist echivalent cu automatul N, diferenele constau n faptul c pentru fiecare mulime de stri Q n care poate s ajunga automatul pentru un prefix al irului x se consider pentru construirea mulimii Q' de stri urmtoare numai simbolul curent din irul x. n momentul n care s-a ajuns la sfritul irului (s-a ajuns la eof) dac n setul strilor curente este inclus i o stare de acceptare (final), atunci rspunsul este "DA" altfel rspunsul este "NU".
S= a= cat S -inchidere({s0}) # -inchidere(S) = {s' Q | s S, s' m(s,)} S caracterul_urmtor timp a eof executa = -inchidere(move(S,a)) # move(S,a) = m(s',a) s' S a = caracterul_urmtor

daca S F atunci rezultat "DA" altfel rezultat "NU"

Algoritmul poate s fie implementat eficient utiliznd dou liste i un vector indexat cu strile automatului finit nedeterminist. ntr-o list se pstreaz setul strilor curente ale automatului, n cealalt setul strilor urmtoare. Utiliznd algoritmul de calcul al starilor urmtoare pentru -tranziii se calculeaz setul -nchidere pentru o stare dat. Vectorul este utilizat pentru a asigura funcionarea listei ca o mulime n sensul c dac o stare este coninuta n list atunci ea nu trebuie s mai poat fi adaugat. Dup ce s-a terminat calculul -inchiderii pentru o stare se face schimbarea rolului celor dou liste. Deoarece fiecare stare are cel mult dou tranziii, fiecare stare poate s produc cel mult dou stri noi. Fie |N| numrul de stri pentru AFN. Deoarece n lista pot s fie memorate maximum |N| stri, calculul strii urmtoare se poate face ntr-un timp proporional |N|. Deci timpul necesar pentru simularea AFN pentru irul de intrare x va fi proportional cu |N| x |x|. S relum de exemplu automatul :

46

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

47

---------------+ / | / +-+ +-+ | / | |a | | | / / > |2|->|3|\ | / / || || \| +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ | | | |/ | |? | |a | |b | |b |--| > |0|->|1| |6|->|7|->|8|->|9|->|10| | | | |\ /| | | | | | | | |--| +-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ | |b | | / /\ \ > |4|->|5|/ / \ || || / \ +-+ +-+ / \ / --------------------

Acest AFN accept expresia regulata (a|b)*abb. S considerm de exemplu irul de intrare x = ab. Evoluia celor dou liste va fi urmtoarea :

lista 1 a ---------> -i({0}) = {0,1,2,4,7}

lista 2

-i({3,8}) = {1,2,3,4,6,7,8}

b <------------i({5,9}) = {1,2,4,5,6,7,9}

Se observ c s-a ajuns la mulimea {1,2,4,5,6,7,9} care nu conine o stare de acceptare deci irul x nu este acceptat de ctre automat.

1.3.1.6. Probleme de implementare pentru automatele finite deterministe i nedeterministe


n compilatoare, automatele finite sunt utilizate pentru implementarea analizoarelor lexicale. Specificarea atomilor lexicali se face sub forma de expresii regulate. Din acest motiv este interesant s discutm modul n care pornind de la o expresie regulat putem s ajungem la un program care s realizeze "execuia" sau altfel spus simularea automatului finit corespunztor. Din cele prezentate anterior se observa c dndu-se o expresie regulat r i un ir de intrare x exist doua metode pentru a verifica dac x L(r). Se poate construi automatul finit nedeterminist (AFN) corespunztor expresiei regulate. Dac expresia regulata r conine |r| simboli atunci aceasta construcie se face ntr-un timp proportional cu |r|. Numrul maxim de stri pentru AFN este de maximum 2 x |r|, iar numrul de tranziii pentru fiecare stare este 2 (conform construciei), deci memoria maxim necesar pentru tabela de tranziii este proporional cu |r|. Algoritmul de simulare pentru AFN are un 47

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

48

numr de operaii proporional cu |Q| x |x| deci cu |r| x |x| (unde |x| reprezint lungimea irului x). Dac |x| nu este foarte mare soluia este acceptabil. O alt abordare posibil este construirea automatului finit determinist (AFD) corespunztor automatului finit nedeterminist construit pornind de la expresia regulat. Simularea AFD se face ntr-un timp proporional cu |x| indiferent de numrul de stri ale AFD. Aceast abordare este avantajoas dac este necesar verificarea a mai multor iruri de lungime mare pentru o aceai expresie regulat (vezi de exemplu situaia n care un editor de texte are o funcie de cutare pentru un subir de o form general dat). Pe de alta parte exist expresii regulate pentru care AFD-ul necesit un spaiu de memorie exponenial n numrul de simboli i operatori din expresia regulata. S considerm de exemplu expresia : (a|b)*a(a|b)(a|b)...(a|b) care reprezint un ir de simboli a i b i care se termina cu (n -1) simboli (a|b). irul reprezentat de aceasta expresie regulat este format din cel puin n simboli a i b, astfel nct exist un simbol a pe poziia n de la sfritul irului. Se observ c un AFD pentru recunoaterea acestei expresii trebuie s memoreze ultimele n caractere, deci sunt necesare cel puin 2n stri (pentru a codifica toate combinaiile posibile de caractere a i b de lungime n). O alta abordare este de a utiliza un AFD, fr a construi intreaga tabela de tranzitii. Ideea este de a determina o tranziie numai dac este necesar. Odat calculat o tranziie aceasta este memorat ntr-o memorie asociativ. Ori de cte ori este necesar o tranziie se face o cutare n memoria asociativ. Concentrnd rezultatele se obine urmtoarea tabel : AFN O(|r|) O(|r|) O(|r| x |x|) AFD O(|r| x |T|) O(c |r|) O(|x|)

complexitate construcie memorie ocupat complexitate simulare

1.3.1.7. Minimizarea numrului de stari pentru AFD


Se poate demonstra c fiind dat o mulime regulata exist un unic automat finit determinist cu numr minim de stari care accept limbajul generat de mulimea respectiv. n cele ce urmeaz considerm c automatul finit are funcia de tranziie definit pentru ntreg domeniul Q X T. Dac exist combinaii (s,i) Q x T pentru care m(s,i) nu este definit considerm o extindere a automatului pentru care adaugm o stare d. Pentru i T, m(d, i) = d, pentru s Q, i T pentru care m(s,i) este nedefinit n automatul iniial vom considera c m(s, i) = d. Construim o extensie a funciei m, m : x T* Q n modul urmtor : 1. ( s Q) (m(s, ) = s) 2. ( s Q)( w T*)(i I)(m(s, wi) = m(m(s, w), i) Fie w T* spunem c w separ strile s, t Q dac i numai dac m(s,w) F i m(t,w) F sau m(t,w) F i m(s,w) F. Un automat este redus dac i numai dac pentru oricare dou stari q1, q2 F exist o secven de intrare care s le separe. Problema construirii automatului redus echivalent unui

48

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

49

automat dat este de fapt problema construirii partiilor induse de o relaie de echivalen. Iniial, considerm ca mulimea Q este imprit n F, Q - F i {d}. Fie P = { Q - F, F, {d}}. n continuare pentru o mulime de stri A P, pentru care |A| > 1, se parcurg simbolii de intrare. Dac pentru un simbol a i strile q1, q2 A, m(q1, a) i m(q2, a) fac parte din elemente diferite din P nseamn c strile succesoare strilor q1 i q2 nu fac parte din aceeai mulime a partiiei. Corespunztor Q va fi mprit n 4 mulimi, etc. Algoritmul corespunztor este: Intrare Un automat finit determinist (Q, T, m, s0, F) Ieire Mulimea mulimilor de stari echivalente din AFD. Descrierea algoritmului este:
P = {F, Q - F, {d}} repeta P' = P repeta alege A P, Q ne marcat si marcheaza A new = daca |A| > 1 atunci alege first A A' = A - {first} cat timp A' executa alege next A' A' = A' - {next} se_imparte = false T' = T cat timp T' si nu se_imparte executa alege a T' T' = T' - {a} goto_first = tranz_AFD[first,a] goto_next = tranz_AFD[next, a] daca goto_next si goto_first sunt n elemente (multimi) diferite din P atunci new = new {next} se_imparte = true

daca new atunci P = P - {A} A = A - new P = P {A}{new} pana nu mai exist A P ne marcat pana P = P'

49

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

50

Algoritmul utilizat nu este optim din punct de vedere al timpului de execuie. La fiecare pas mulimea de stri Q se mparte n cel mult dou noi mulimi : new i Q \ new. Exist algoritmi pentru care numrul de operaii este proporional cu n log n. S considerm urmtorul exemplu :
b --\/ +---+ | | b b > | 2 |<---------------------+ / +-| | | +---+ /a | +---+ | start | |/ | +---+ +---+ +------+ -------| 0 | a \/| | b | |b |+----+| | |---> | 1 |---->| 3 |--->|| 4 || +---+ | | | | |+----+| +---+ +---+ +------+ /\ || a | | -- |+-<--------+ | a| | | a | +--<--------------------+

Iniial P = {{0, 1, 2, 3}, {4}}, A = {0, 1, 2, 3}. Fie first = 0, next = 1, m(0, a), m(1, a) A; m(0, b), m(1, b) A. Pentru next = 2, m(0, a) A, m(2, a) A; m(0, b) A, m(2,b) A. Continund pentru next = 3, m(0, b) A dar m(3, b) A, deci new = {3}. S-a obinut P = {{0, 1, 2}, {3}, {4}}. Se observ c P P'. Urmeaz A = {0, 1, 2}. Se obine m(0, b) Q dar de aceasta data m(1, b) A. Rezult P = {{0, 2}, {1}, {3}, {4}}. Pentru A = {0, 2} se obine m(0, a), m(2, a) {1}; m(0, b), m(2, b) A. Se obine automatul finit determinist cu numr minim de stri:
b b ---------<--------------------+ \/ / | +---+ / | start | |/ +---+ +---+ +-----+ -----> |02 | a | | b | |b |+---+| | |--->| 1 |---->| 3 |--->|| 4 || +---+ | | | | |+---+| +---+ +---+ +-----+ /\ || a | | -- |+-<--------+ | a| | | a | +--<--------------------+

50

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

51

1.3.2. Automate cu stiv(pushdown)


Un astfel de automat are o memorie organizat ca o stiv :
+--------------|a0|a1|...|an| banda de intrare de tip (read only) +--------------\ cap de citire \ +---------+ | unitate | +----+ | de |---| z1 | | control | |----| +---------+ | z2 | |----| |... | memoria stiva | | |----| | zn | +----+

Un automat pushdown (PDA) este un obiect matematic definit n modul urmtor: P = (Q, T, Z, m, q0, z0, F) unde: Q - este o mulime finit de simboli ce reprezint strile posibile pentru unitatea de control a automatului; T - este mulimea finit a simbolilor de intrare; Z - este mulimea finit a simbolilor utilizai pentru stiv; m - este o funcie, m : S x (T {}) x Z P(S x Z*) este funcia care descrie modul n care se obine starea urmtoare i informaia care se introduce n stiv pentru o combinaie stare, intrare, coninut stiv dat; q0 Q este starea iniial a unitii de control; z0 Z este simbolul aflat n vrful stivei n starea iniial; F Q reprezint mulimea finit a strilor finale. O configuraie de stare a automatului este un triplet (q, w, a) Q x T* x Z* unde : q - reprezint starea curent a unitii de control; w - reprezint partea din banda de intrare care nu a fost nc citit. Dac w = nseamn c s-a ajuns la sfritul benzii de intrare; a - reprezint coninutul stivei.

O tranziie a automatului este reprezentat prin relaia |- asupra mulimii configuraiilor automatului, este definit n modul urmtor : (q, aw, z) |- (q', w, ) unde (q', ) m(q, a, z), q Q, a T {}, w T*, z Z, a Z*. Dac a nseamn c, dac unitatea de control este n starea q, capul de citire este pe simbolul a iar simbolul din vrful stivei este z atunci automatul poate s i schimbe

51

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

52

configuraia n modul urmtor : starea unitii de control devine q', capul de citire se deplaseaz cu o poziie la dreapta iar simbolul din vrful stivei se inlocuiete cu . Dac a = nseamn c avem o -tranziie pentru care simbolul aflat n dreptul capului de citire pe banda de intrare nu conteaz (capul de citire nu se va deplasa), ns starea unitii de control i coninutul memoriei se pot modifica. O astfel de tranziie poate s aibe loc i dupa ce s-a parcurs ntreaga banda de intrare. Dac se ajunge ntr-o configuraie pentru care stiva este goal nu se mai pot executa tranziii. Relatia |- se poate generaliza la |-i, |-+, |-*, ntr-o manier similar relaiei de derivare pentru forme propoziionale. O configuraie iniial pentru un automat push down este o configuraie de forma (q0, w, z0) unde w T*. O configuraie final este o configuraie de forma (q, , ) cu q F, Z*. Spunem c un ir w este acceptat de un automat push down prin stri finale dac (q0, w, z0) |-* (q, , ) pentru q F i Z*. Limbajul acceptat de un automat pushdown P n acest mod se noteaz cu L(P). S considerm de exemplu automatul push down care accept limbajul L = {0n1n | n > 0}. P = ({q0, q1 ,q2}, {0,1}, {z, 0}, m, q0, z,{q0}) unde
m(q0,0,z) m(q1,0,0) m(q1,1,0) m(q2,1,0) m(q2,,z) = = = = = {(q1,0z)} {(q1,00)} {(q2,)} {(q2,)} {(q0,z)}

Pentru toate celelalte elemente (s, a, z) Q x (T {}) x Z care nu sunt descrise de regulile de mai sus, m(s, a, z) = . Se observ c automatul copiaz toate zerourile de pe banda de intrare n stiv i apoi descarc stiva pentru fiecare simbol 1 ntlnit la intrare. De exemplu pentru irul 0011, automatul va executa urmtoarea secven de tranziii :
(q0,0011,z) |||||(q1,011,0z) (q1,11,00z) (q2,1,0z) (q2,,z) (q0,,z)

Pentru irul de intrare 011 care nu aparine limbajului evoluia va fi :


(q0,011,z) ||||(q1,11,0z) (q2,1,z) (q2,1,z) (q0,1,z)

Se observ c dei s-a ajuns ntr-o stare final nu s-a ajuns la sfritul irului de intrare deci irul nu a fost acceptat. Pentru irul de intrare 001, evoluia este :
(q0,001,z) |- (q1,01,0z) |- (q1,1,00z) |- (q2,,0z)

n acest caz s-a ajuns la sfritul irului dar starea n care se gseste automatul nu este final deci nici acest ir nu este acceptat.

52

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

53

Pentru a demonstra c L(P) = {0n1n} trebuie s aratm c {0n1n} L(P) i L(P) {0n1n}. Se pot face urmtoarele observaii :
(q0,0,z) |- (q1,,0z) (q1,0i,0z) |-i (q1,,0i+1z) (q1,1,0i+1z) |- (q2,,0iz) (q2,1i,0iz) |-i (q2,,z) (q2,,z) |- (q0,,z)

Rezult c pentru irul 0n1n, n > 1 se obine :


(q0,0n1n,z) |-2n+1 (q0, , z), n > 1 (q0,,z) |-0(q0,,z)

Deci {0n1n} L(P). Trebuie s artm c i L(P) {0n1n} . Se observ c pentru a accepta un ir, P trece n mod obligatoriu prin succesiunea de stri q0, q1, q2, q0 dac n > 0. Dac (q0, w, z) |-i (q1, , ), i > 1 nseamn ca w = 0i i = 0iz. Dac (q2, w, ) |-i (q2, , ) nseamn c w = 1i i a = 0i. Dac (q1, w, ) |- (q2, , ) nseamn c w = 1 i a = 0 Dac (q2, w ,z) |-* (q0, , z) nseamn c w = . Deci dac (q0, w, z) |-i (q0, , z) atunci fie w = i i = 0 fie w = 0n1n, i = 2 n + 1. Deci L(P) {0n1n} . S considerm i automatul care accept limbajul L = {wwR|w {a,b}+}, P = ({q0, q1, q2}, {a, b}, {z, a, b}, m,q0, z, {q2}) unde :
m(q0,a,z) m(q0,b,z) m(q0,a,a) m(q0,a,b) m(q0,b,a) m(q0,b,b) m(q1,a,a) m(q1,b,b) m(q1,,z) = = = = = = = = = {(q0,az)} {(q0,bz)} {(q0,aa),(q1,)} {(q0,ab)} {(q0,ba)} {(q0,bb),(q1,)} {(q1,)} {(q1,)} {(q2,)}

Funcionarea automatului pentru recunoaterea unui ir parcurge trei etape. n prima etap se copiaz n stiv irul w, apoi stiva se descarc pentru wR. Ultima etap recunoate sfritul irului de intrare n condiiile descrcrii complete a stivei. Prima etap este caracterizat de starea q0, urmtoarea de q1, q2 fiind starea final. n prima etap dac simbolul curent de pe banda de intrare nu coincide cu simbolul din vrful stivei atunci nu s-a ajuns la sfritul irului w i deci simbolul aflat sub capul de citire este copiat n vrful stivei. Dac ns simbolul curent de pe banda de intrare coincide cu simbolul din vrful stivei atunci fie s-a ajuns la sfritul irului w i ncepe wR i deci trebuies nceap descrcarea stivei fie nu s-a ajuns la sfritul irului w i atunci simbolul aflat sub capul de citire trebuie s fie copiat n vrful stivei. Din cele prezentate anterior rezult caracterul nedeterminist al automatului. S considerm de exemplu secvena de miscri pentru irul abba.

53

Irina Athanasiu
(1) (q0,abba,z) ||||-

10/4/2003
(q0,bba,az) (q0,ba,baz) (q0,a,bbaz) (q0,,abbaz)

Limbaje formale si translatoare

54

Se observ c pentru aceast secven de tranziii nu se ajunge ntr-o stare final. Automatul fiind nedeterminist trebuie s cercetm ns toate secvenele de tranziii posibile. O alt secven este:
(2) (q0,abba,z) |||||(q0,bba,az) (q0,ba,baz) (q1,a,az) (q1,,z) (q2,,)

Rezult ca automatul ajunge n starea q2 deci accept irul abba. Fie P = (Q, T, Z, m, q0, z0, F) un automat pushdown. Spunem c un ir w T* este acceptat de P prin stiva goal dac (q0, w, z0) |-+ (q, , ) pentru q Q. Fie Le(P) mulimea irurilor acceptate de P prin stiva goal. Se poate demonstra urmtorul rezultat. Dac L(P) este limbajul acceptat de automatul P prin stri finale atunci se poate construi un automat pushdown P' astfel nct L(P) = Le(P'). Automatul P' va simula funcionarea automatului P. Ori de cte ori P intr ntr-o stare final, P' poate continua simularea sau intr ntr-o stare speciala qe n care golete stiva (qe Q). Se poate ns observa c P poate s execute o secven de micri pentru un ir de intrare w care s permit golirea stivei fr ca irul s fie acceptat de ctre automatul P (pentru P nu conteaz dect ajungerea ntr-o stare final). Pentru a evita astfel de situaii se consider un simbol special pentru iniializarea stivei, simbol care nu poate s fie scos din stiva dect n starea qe. Fie P' = (Q {qe, q'}, T, Z {z'}, m', q', z', ) unde funcia m' este definit n modul urmtor : 1. dac (r, t) m(q, a, z) atunci (r, t) m'(q, a, z), pentru r, q Q, t Z*, a T {}, z Z. 2. m'(q', , z') = {(q0, z0z')}. P' i iniializeaz stiva cu z0z' (z' reprezint simbolul de iniializare al stivei pentru P'). 3. pentru q F i z Z, (qe, ) m'(q, , z); 4. pentru z Z {z'}, m'(qe, , z) = {(qe, )} Se observ c :
(q',w,z') |- (q0,w,z0z') |-n (q, , y1 y2 ... yr) |- (qe, , y2 ... yr) |-r-1 (qe, , )

cu yr = z' dac i numai dac (q0, w, z0) |-n (q, , y1 y2 ... yr-1) pentru q F i y1 y2 ... yr-1 Z*. Deci Le(P') = L(P). Se poate demonstra i rezultatul invers, adic dndu-se un automat push down i limbajul acceptat de acesta prin stiva goal se poate construi un automat push down care accept acelai limbaj prin stri finale. Limbajele acceptate de automatele pushdown sunt limbajele care pot s fie descrise de gramatici independente de context. Dndu-se o gramatic independent de context s 54

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

55

construim automatul care accept limbajul generat de aceasta gramatica. Fie G = (N, T, P, S), se obine automatul pushdown R = ({q}, T, N T, m, q, S, ) unde m este construit conform urmtoarelor reguli : 1. dac A P atunci (q, ) m(q, , A) 2. m(q, a, a) = {(q, )} pentru orice a T. Se observ c automatul astfel construit va accepta limbajul prin stiv goal. Se poate arata c A k w dac i numai dac (q,w,A) |-n (q, , ) k, n > 1. Altfel spus exist o derivare S + w dac i numai dac (q, w, S) |-+ (q, , ). Rezult deci c L(G) = L(R). S construim de exemplu automatul care recunoate gramatica expresiilor aritmetice G = ({, T, F}, {a, +, (, )}, P, ) unde P = { + T | T, T T * F | F, F () | a}. Aplicnd construcia propus rezult R = ({q}, {a, +, *, (, )},{, T, F, a, +, *, (, )}, m, q, , ) unde m este definit n modul urmtor :
m(q, m(q, m(q, m(q, , , , b, ) T) F) b) = = = = {(q, {(q, {(q, {(q, + T),(q, T)} T * F),(q, F)} ()),(q, a)} )} cu b {a,+,*,(,)}.

S considerm de exemplu o succesiune de configuraii pentru a + a * a.


(q, a + a * a, ) |||||||||||||(q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, a + a * a, a + a * a, a + a * a, a + a * a, + a * a, + a * a, T) a * a, T * a * a, F * a * a, a * * a, * F) a, F) a, a) , ). + T+ F+ a+ T) F) F) F) T) T) T) T)

n reprezentarea tranziiilor vrful stivei a fost reprezentat n stnga. Se observ c secvena de tranziii considerat, simuleaz urmtoarea secven de derivri de forme propoziionale :
+TT+TF+Ta+Ta+T*F a + F * F a + a * F a + a * a.

Se observ ca n aceasta secven s-a nlocuit ntotdeauna cel mai din stnga neterminal. Din acest motiv se spune c am utilizat o derivare stnga. Secvena de derivri anterioare poate s fie reprezentat de urmtorul arbore de derivare.

55

Irina Athanasiu

10/4/2003
/|\ /|\ + T | /|\ | /|\ T T * F | | | | | | F F a | | a a

Limbaje formale si translatoare

56

Acest gen de construire de secvente de derivare i deci automatele pushdown care accept limbaje prin stiv goal sunt utilizate n analiza sintactic top down (descendent recursiv). Un tip special de automat cu stiv l reprezint automatul pushdown extins = (Q, T, Z, m, q0, z0, F) pentru care m : Q x (T {}) x Z* P(Q x Z*). Se observ c n acest caz din stiv se consider nu numai simbolul din vrful stivei ci un ir de simboli plasat n vrful stivei. Considerm pentru acest tip de automat c acceptarea se face prin stari finale ( i n acest caz se poate construi un automat echivalent care s faca acceptarea prin stiv goal). S considerm de exemplu automatul care accept limbajul L = {wwR | w {a,b}*}. Fie P = ({q, p}, {a, b}, {a,b,S,z}, m, q, z, {p}) unde funcia m este definit n modul urmtor :
m(q,a,) = {(q,a)} m(q,b,) = {(q,b)} m(q,,) = {(q,S)} m(q,,aSa) = {(q,S)} m(q,,bSb) = {(q,S)} m(q,,Sz) = {(p,)}

De exemplu pentru secvena de intrare aabbaa este posibil urmtoarea secven de tranziii :
(q, aabbaa, z) |||||||||||(q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (p, abbaa, az) bbaa, aaz) baa, baaz) baa, Sbaaz) aa, bSbaaz) aa, Saaz) a, aSaaz) a, Saz) , aSaz) , Sz) , )

Se observ ca datorit tranziiei m(q, , ) = {(q, S)} automatul este nedeterminist. Se poate demonstra c pentru orice automat pushdown extins , exist un automat pushdown P astfel nct L() = L(P). S revenim la problema acceptrii limbajelor independente de context de ctre automate pushdown i s considerm din nou exemplul expresiilor aritmetice. Pentru generarea irului a + a * a putem s considerm i urmtoarea secven de derivari : +T+T*F+T*a+F*a + a * a T + a * a F + a * a a + a * a. 56

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

57

Se observ ca n aceast secven s-a nlocuit ntotdeauna cel mai din dreapta neterminal. Din acest motiv se spune ca s-a construit o derivare dreapta. Considernd acest tip de derivri i parcurgndu-le n ordine invers (de la sfrit) se poate introduce noiunea de reducere stnga. Fie gramatica G = (N,T,P,S) o gramatic independent de context s presupunem c S * aAw aw * xw. Dac n fiecare derivare a fost nlocuit de fiecare dat neterminalul cel mai din dreapta atunci se spune c aw se reduce stnga la aAw dac A P. Dac este cel mai din stnga astfel de ir atunci spunem ca este nceputul irului aw. Deci un capt (handle) pentru o derivare dreapta este orice ir care este partea dreapta a unei producii i poate s fie nlocuit de neterminalul corespunztor ntr-o form propoziional care a aprut dintr-o derivare dreapta obinndu-se forma propoziional anterioar din derivarea dreapta. S considerm de exemplu gramatica: G = ({S, A, B},{a, b, c, d}, {S Ac | Bd, A aAb | ab, B aBbb | abb}, S). Aceast gramatic genereaz limbajul {anbnc | n > 1} {anb2nd | n > 1}. S considerm urmtoarea secven de derivari S Bd aBbbd aabbbbd. Pentru irul obinut abb este capt deoarece aBbbd este o form propoziional anterioar din derivarea dreapta, n timp ce ab nu este deoarece aAbbbd nu este o forma propoziional care poate s apar ntr-o derivare dreapta. Relund din nou gramatica pentru expresii aritmetice i secvena de derivri dreapta : +T+T*F+T*a+F*a + a * a T + a * a F + a * a a + a * a. Rezult arborele de derivare :
/|\ /|\ + T | /|\ | /|\ T T * F | | | | | | F F a | | | | a a

Dac analizm acest arbore se vede c a (care reprezint frunza celui mai din stnga subarbore) este un nceput, dac se face o reducere se obine arborele :

57

Irina Athanasiu

10/4/2003
/|\ /|\ + T | /|\ | /|\ T T * F | | | | | | F F a | | a

Limbaje formale si translatoare

58

Continund se ajunge la :
/|\ /|\ + T /|\ /|\ T * F | | F a | a

Urmtorul capt este a, etc. Se observ c pentru a identifica un capt pentru o form propoziional obinut printro derivare dreapta se consider secvena frunzelor celui mai din stnga subarbore de adincime 1 (toate nodurile acestuia sunt fie frunze fie noduri din care se deriveaz frunze). De exemplu :
| | | a sau F sau T sau T /|\ / | \ T * F

pentru care a, F, T respectiv T * F reprezint pri dreapta ale unor producii. Aceasta metoda de reducere a arborilor de derivare se numete "handle pruning". Dndu-se o gramatic independent de context G = (N, T, P, S) se poate construi un automat pushdown extins care s opereze conform metodei "handle pruning" n modul urmtor : R = ({q, r},T,N T {$}, m, q, $, {r}) unde: 1. dac A P atunci (q, A) m(q, , ) 2. m(q, a, ) = {(q, a)} pentru orice a T. Se observ c simbolii a T sunt copiai n stiva; 3. m(q, , $S) = {(r, )}. S construim utiliznd aceast tehnic automatul pushdown extins care accept gramatica expresiilor aritmetice : R = ({q, r},{a, +, *, (, )},{a, +, *, (, ), T, F, , $}, m, q, $,{r}) unde

58

Irina Athanasiu
m(q, m(q, m(q, m(q, m(q, m(q, m(q, m(q, b, , , , , , , ,

10/4/2003

Limbaje formale si translatoare

59

) = {(q, b)}, pentru b {a, +, *, (, )} + T) = {(q, )} T) = {(q, )} T * F) = {(q, T)} F) = {(q, T)} ()) = {(q, F)} a) = {(q, F)} $) = {(r, )}

Find vorba de o derivare dreapta, vrful stivei a fost figurat n dreapta. Se observ c aceast secven de tranziii este unica secven ce duce la acceptarea irului de intrare. Pentru irul a + a * a, automatul R va executa urmtoarele tranziii :
(q, a + a * a, $) ||||||||||||||(q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, + a * a, $a) + a * a, $F) + a * a, $T) + a * a, $) a * a, $ +) * a, $ + a) * a, $ + F) * a, $ + T) a, $ + T *) , $ + T * a) , $ + T * F) , $ + T) , $) , ?)

Automatele push down construite dup modelul prezentat anterior vor fi utilizate n analiza sintactic de tip bottom-up. Un automat push down este determinist dac pentru orice configuraie exist cel mult o singur tranziie urmtoare. Mai precis un automat push down PD = (Q, T, Z, m, q0, z0, F) este determinist dac pentru orice (q, a, z) x (T {}) x Z sunt ndeplinite urmtoarele condiii: 1. |m(q, a, z)| 1, 2. dac m(q, , z) atunci m(q, a, z) = pentru a T Avnd n vedere echivalena dintre un automat push down i limbajele independente de context, vom spune c un limbaj independent de context este determinist dac este acceptat de un automat push down determinist. Vom modifica puin condiia de acceptare, considernd c un limbaj independent de context este determinist dac exist un automat pushdown determinist care accept limbajul L$. Simbolul $ este un simbol care nu apare n alfabetul peste care este definit limbajul L. Se observ c utilizarea acestui simbol care apare concatenat cu fiecare ir din L indic de fapt posibilitatea automatului push down de a recunoate sfritul irului. n acest mod se extinde puin clasa limbajelor independente de context deterministe. Se pune intrebarea dac orice limbaj independent de context este determinist. S considerm de exemplu limbajul : L = {wwR | w {a, b, c}

59

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

60

Evident un automat push down care accept acest limbaj trebuie s ghiceasc unde este mijlocul irului pentru ca s nceap descrcarea stivei. Intutitiv, o astfel de operaie nu se poate realiza cu un dispozitiv determinist. Propoziie. Clasa limbajelor acceptate de automate push down nedeterministe este mai larg dect clasa limbajelor acceptate de automate push down deterministe.

1.3.3 Maina Turing


O main Turing este un acceptor care "tie" s scrie pe banda de intrare. n acest mod banda de intrare devine memorie auxiliar. Maina Turing a fost definit de ctre matematicianul englez Alan Turing (1912 - 1954) n anul 1930. Cnd a inventat maina care i poart numele, Turing era interesat nu de calculatoare ci de posibilitatea specificri i rezolvri problemelor matematice utiliznd mijloace automate. Adic, poate s fie rezolvat orice problema matematic utiliznd nite reguli elementare de prelucrare a irurilor ?. Structura unei maini Turing este:
+---------------------------| +---------------------------

banda de intrare

| cap de citire / scriere | +---------+ | unitate | | de | | control | +---------+

Unitatea de control comand execuia micrilor. O micare este format din : stabilirea strii urmtoare pentru unitatea de control; scrierea unui simbol pe banda de intrare sau execuia unei deplasri cu o poziie spre stnga sau spre dreapta.

Banda de intrare este marginit la stnga i infinit la dreapta. Dup poziia ocupat de irul de intrare pe banda aceasta conine blancuri. n cele ce urmeaz vom indica simbolul blanc cu ajutorul caracterului # (presupunnd c acest simbol nu face parte din alfabetul limajului pentru care se construiete maina). De asemenea vom utiliza caracterele L i respectiv R pentru a indica o deplasare la stnga respectiv la dreapta. Maina Turing poate s scrie pe banda de intrare, deci poate s scrie att informaii intermediare ct i un rspuns nainte de a se oprii. Maina Turing are o stare special numit stare de oprire (de halt) pe care o vom nota n continuare cu h. Acceptarea sau neacceptarea unui ir este indicat de coninutul benzii cnd se ajunge n starea de oprire. S considerm o definiie formal a noiunii de main Turing. Se numete main Turing obiectul matematic : MT = (Q, T, m, q0) unde Q este o mulime finit a strilor mainii Turing, h Q; 60

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

61

T este alfabetul finit de intrare care conine simbolul # dar nu conine simbolii L i R; m este funcia de tranziie m : Q x T (Q {h}) x (T {L, R}).

q0 Q este starea iniial a mainii Turing;

Dac q Q, a T i m(q, a) = (p, b) nseamn c fiind n starea q, avnd a sub capul de citire maina trece n starea p. Dac b T atunci simbolul a va fi inlocuit cu b, altfel capul se va deplasa cu o poziie la stnga sau la dreapta n funcie de valoarea simbolului b {L, R}. Se observ c maina Turing a fost definit ca un acceptor determinist. ncetarea funcionrii mainii Turing se face dac se ajunge n starea h (cnd maina se oprete) sau dac se ncearc deplasarea la stnga dincolo de captul din stnga al benzii. n acest ultim caz se spune ca maina s-a agat (a ajuns ntr-o stare de agare - hanging state). Definiia anterioar corespunde maiii Turing standard. Fa de aceast definiie exist diferite variante. S considerm un exemplu de main Turing MT = ({q0, q1}, {a, #}, m, q0), unde:
m(q0, m(q0, m(q1, m(q1, a) #) a) #) = = = = (q1, (h, (q0, (q0, #) #) a) R)

S considerm c pe banda de intrare se gsete irul aaa i c poziia capului este pe primul caracter din ir. Se observ c pentru aceast stare iniial, primul simbol a este nlocuit cu #, noua stare find q1. Pentru q1, dac sub capul de citire se gsete un caracter # atunci se va face o deplasare la dreapta starea devenind q0. Se continu evoluia ntr-o manier similar pn cnd n starea q0 capul de citire se gasete pe un caracter #. n acest moment se trece n starea h i maina se oprete. Rezult ca evoluia mainii duce la tergerea unui ir de a-uri nscris pe banda de intrare. S considerm i urmtorul exemplu MT = ({q0}, {a, #}, m, q0), unde
m(q0, a) = (q0, L) m(q0, #) = (h, #)

n acest caz maina caut primul simbol # la stnga poziiei din care pleac capul de citire / scriere. La gsirea acestui simbol se trece n starea h. Dac nu exist un astfel de simbol maina nceteaz s funcioneze cnd ajunge la captul din stnga al benzii. O configuraie pentru o main Turing este un element din mulimea : (Q {h}) x T* x T x (T* (T - {#}) {}) Elementele unei configuraii sunt: starea curent q (Q {h}) irul aflat pe banda de intrare la stnga capului de citire / scriere (a T*) simbolul aflat sub capul de citire / scriere ( i T) irul aflat la dreapta capului de citire / scriere ( (T* (T - {#}) {})). Se observ c, deoarece irul de intrare este finit, n timp ce banda de intrare este infinit la dreapta putem s considerm ntotdeauna c irul se termin cu un caracter care nu este # (oricum n continuare pe band apar numai caractere #). Deci o configuraie este de forma

61

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

62

(q, a, i, ). Pentru simplificare, o configuraie se poate reprezenta i sub forma (q, ai), subliniind simbolul pe care se gsete capul de citire / scriere. Asupra configuraiilor se poate defini o relaie de tranziie |- n modul urmtor. Fie (q1, w1, a1, u1) i (q2, w2, a2, u2) dou configuraii. Atunci: (q1,w1,a1,u1) |- (q2,w2,a2,u2) # w1 a1 u1 # # w1 a1 u1 # # w1 a1 u1# # w2 a2 u2 # # w2 a2 u2# # w2 a2 u2 # dac i numai dac exist b T {L, R} astfel nct m(q1, a1) = (q2, b) i este ndeplinit una dintre urmtoarele condiii :

62

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

63

1. b T, w1 = w2, u1 = u2, a2 = b; 2. b = L, w1 = w2a2 dac a1 # sau u1 atunci u2 = a1 u1 altfel u2 = /* capul de citire / scriere este poziionat dup irul de intrare */ 3. b = R, w2 = w1a1 dac u1 = atunci u2 = a2 = # altfel u1 = a2 u2 n cazul 1 se face nlocuirea simbolului curent de pe banda de intrare (a) cu b. n al doilea caz este descris o micare la stnga, respectiv n cazul 3 se descrie o micare la dreapta. Dac b = L i w1 = atunci (q1, w1, a1, u1) nu are o configuraie urmtoare, n acest caz se spune c (q1, w1, a1, u1) este o configuraie de agare, maina find ntr-o stare de agare (hanging state). Pentru relaia |- se poate considera inchiderea reflexiv i tranzitiv notat cu |-*. Un calcul efectuat de o maina Turing este o secven de configuraii c0, c1, ..., cn astfel nct n 0 i c0 |- c1 |- ... |- cn. Se spune despre calcul c are loc n n pai. Termenul de calcul nu a fost utilizat ntimpltor. Se poate considera c o main Turing tie s evalueze funcii definite pe iruri de simboli cu valori n iruri de simboli. Dac T1 i T2 sunt doua mulimi alfabet care nu conin simbolul #, s considerm funcia f : T1* T2*. Spunem ca MT = (Q, T, m, s) calculeaz f dac T1, T2 T i pentru orice ir w T1* dac u = f(w), u T2*, atunci (s, #w#) |-* (h, #u#). Se observ c s-a considerat c capul este poziionat dup sfritul irului de intrare att la nceputul execuiei ct i la sfritul acesteia. Dac pentru o funcie f dat exist o maina Turing care o calculeaz spunem c funcia f este Turing calculabil. S considerm de exemplu maina Turing MT = ({q0, q1, q2}, {a, b, #}, m ,q0) unde funcia m este definit n modul urmtor :
m(q0, m(q0, m(q0, m(q1, m(q1, m(q1, m(q2, m(q2, m(q2, a) b) #) a) b) #) a) b) #) = = = = = = = = = (q1, (q1, (q1, (q0, (q0, (q2, (q2, (q2, (h, L) L) L) b) a) R) R) R) #)

S considerm evoluia pentru irul de intrare aab.


(q0, #aab#) |||||||||(q1, (q0, (q1, (q0, (q1, (q0, (q1, (q2, (q2, #aab#) #aaa#) #aaa#) #aba#) #aba#) #bba#) #bba#) #bba#) #bba#)

63

Irina Athanasiu
|- (q2, #bba#) |- (q2, #bba#) |- (h, #bba#)

10/4/2003

Limbaje formale si translatoare

64

Pentru irul vid evoluia este :


(q0, ##) |- (q1, ##) |- (q2, ##) |- (h, ##)

Funcia calculat de aceast main Turing este funcia de interschimbare a caracterelor a i b. Din domeniul irurilor putem s trecem n domeniul numerelor naturale considernd reprezentarea unar a numerelor naturale. Adic utiliznd un alfabet I care conine un singur simbol, I diferit de #, reprezentarea unui numr natural n este data de irul = In. Se observ c numrul 0 este reprezentat de irul vid. n acest caz o funcie f : N N este calculat de o main Turing, dac aceasta calculeaz f' : I* I* unde f'() = cu In i If(n) pentru orice numr natural. De la un singur argument funcia f se poate extinde la mai multe argumente - f : Nk N pentru care corespunde f' : (I {,})* I* cu f'() = pentru un ir de forma i1, i2, ..., ik ,... ij Inj, 1 j k, i If(n1,...,nk). S considerm de exemplu funcia succesor f(n) = n + 1, n numr natural. MT = ({q0}, {i, #}, m, q0) cu
m(q0, i) = (h, R) m(q0, #) = (q0, i)

De exemplu (q0, #i#) |- (q0, #iii#) |- (h, #iii#). n general :


(q0, #n#) |- (q0, #ini#) |- (h, #n+1#)

O main Turing poate s fie utilizat i ca acceptor de limbaj. i anume s considerm un limbaj L definit asupra alfabetului T care nu conine simbolii #, D i N. Fie dL : T* {D, N} o funcie definit n modul urmtor - pentru w T*
D / dL(w) = \ N dac w L dac w L

Se spune ca limbajul L este decidabil n sens Turing (Turing decidable) dac i numai dac funcia dL este calculabil Turing. Dac dL este calculat de o maina Turing MT spunem ca MT decide L. S considerm de exemplu limbajul L = {w T* | |w| mod 2 = 0, T = {a}} (limbajul irurilor peste alfabetul T = {a} care au lungimea un numr par). Funcia dL corespunztoare poate s fie calculat de urmtoarea main Turing : MT = ({q0, q1, q2, q3, q4, q5, q6}, {a, D, N, #}, m , q0) unde m este o funcie partial definit n modul urmtor : m(q0, #) = (q1, L) pornim spre stnga

64

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

65

m(q1, a) = (q2, #) se terge un a m(q1, #) = (q4, R) s-au ters un numr par de a m(q2, #) = (q3, L) s-a ters un a se continu spre stnga m(q3, a) = (q0, #) s-au ters doi de a, suntem ca la nceput m(q3, #) = (q6, R) s-a ajuns la stnga cu un numr imapar de a m(q4, #) = (q5, D) s-au ters zero sau un numr par de a m(q5, D) = (h, R) rspuns D i oprire m(q5, N) = (h, R) rspuns N i oprire m(q6, #) = (q5, N) au fost un numr impar de a S considerm evolutia mainii pentru un ir corect : (q0, #aa#) |- (q1, #aa#) |- (q2, #a#) |- (q3, #a#) |- (q0, ##) |- (q1, ##) |- (q4, ##) |- (q5, #D#) |- (h, #D#) Pentru un ir incorect se obine : (q0, #aaa#) |- (q1, #aaa#) |- (q2, #aa#) |- (q3, #aa#) |- (q0, #a#) |- (q1, #a#) |- (q2, ##) |- (q6, ##) |- (q5, #N#) |- (q3, ##) |- (h, #N#) Noiunea de acceptare este mai larg dect noiunea de decidabilitate n legatura cu limbajele. i anume dac L este un limbaj asupra alfabetului T, spunem ca limbajul L este Turing acceptabil dac exist o maina Turing care se oprete dac i numai dac w L. Limbajele Turing decidabile sunt i Turing acceptabile. Reciproca nu este ns adevarat. Fie limbajul : L = {w {a, b}* | w conine cel puin un simbol a} considernd maina Turing MT = ({q0}, {a, b, #}, m, q0) cu m(q0, a) = (h, a) m(q0, b) = (q0, L) m(q0, #) = (q0, L) Se poate constata ca dac pe banda de intrare se gasete un ir din limbaj atunci pornind din configuraia iniial se va face cutarea unui simbol a prin deplasare spre stnga. Dac un astfel de caracter este gsit maina se oprete (deci accept irul). Dac ns pe banda de intrare se gasete un ir care nu aparine limbajului atunci maina va intra n starea de agare dup ce a ajuns la captul din stnga al benzii.

65

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

66

1.3.3.1. Compunerea mainilor Turing


Pentru a evidenia "puterea" de calcul a mainilor Turing vom prezenta mecanismul prin care o main Turing se poate construi pe baza unor maini Turing mai simple. Propoziie Fie MT o maina Turing i fie (qi, wiaiui), (i = 1, 2, 3) maini. Dac sunt posibile evoluiile : (q1, w1a1u1) |-* (q2, ww2a2u2) i (q2, w2a2u2) |-* (q3, w3a3u3) atunci este posibila i evoluia : (q1, w1a1u1) |-* (q3, ww3a3u3) Justificare. n evoluia din (q2, ww2a2u2) n (q3, w3a3u3) maina nu poate s ajunga pe banda de intrare pe un simbol aflat la stnga irului w2 (ntr-o astfel de situaie s-ar ajunge la marginea din stnga a benzii, deci s-ar intra n starea de agare i deci nu s-ar mai ajunge n configuraia urmtoare). Deoarece maina are o funcionare determinist va rezult aceai evoluie i dac irul w2a2u2 nu este la nceputul benzii de intrare. Rezult c este posibil i evoluia (q2, ww2a2u2) |-* (q3, ww3a3u3). Pe baza propoziiei anterioare putem s realizm compunerea mainilor Turing ntr-o manier similar utilizrii subprogramelor. S considerm de exemplu o maina Turing M1 care "stie" s funcioneze primind un ir pe banda de intrare pornind cu capul de citire / scriere poziionat dup ir. S presupunem c M1 nu poate s ntre ntr-o stare de agare. La oprire, capul va fi plasat de asemenea dup irul care a rezultat pe banda de intrare. Dac M1 este utilizat n cadrul unei alte maini Turing care printre alte aciuni pregtete i un ir de intrare pentru M1, atunci dup ce M1 primete controlul nu va depai limita stnga a irului su de intrare, deci nu va modifica un ir care eventual a fost memorat nainte pe banda de intrare. n cele ce urmeaz considerm ca masinile Turing care se combin nu pot s ntre n starea de agare i c fiecare are strile sale proprii diferite de strile tuturor celorlalte maini Turing. Ca maini de baza pornind de la care vom construi noi maini Turing vom considera cteva cu funcionare elementar. Aceste maini au un un alfabet de intrare T comun. 1. exist |T| maini care scriu fiecare cte un simbol din T n poziia curent a capului. O astfel de main este definit ca find Wa = ({q}, T, m, q), a T, m(q, b) = (h, a), b T. Pentru a simplifica notaiile Wa va fi reprezentat de simbolul a. 1. exist dou masini care execut deplasri elementare. i anume VL = ({q}, T, m, q) cu m(q, a) = (h, L) i VR = ({q}, T, m, q) cu m(q, a) = (h, R), a T. Vom nota aceste maini cu L i respectiv R. Reprezentarea compunerii mainilor Turing se face ntr-o manier asemntoare unei structuri de automat finit pentru care o stare este reprezentat de o maina Turing. Intrarea ntr-o stare a automatului corespunde cu iniierea funcionrii unei maini Turing. La oprirea unei maini Turing (intrarea acesteia n starea h) n funcie de simbolul aflat sub capul de citire se va trece ntr-o alt stare, adic se va iniia funcionarea unei alte maini Turing. O schem de main Turing este tripletul = (M, , M0) unde configuraii ale acestei

66

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

67

M este o mulime finit de maini Turing care au toate un alfabet comun T i mulimi de stri distincte; M0 M este maina iniial; este o funcie parial , : M x T M.

O schem de main Turing reprezint o maina Turing compus din mainile care formeaz mulimea M. Funcionarea acesteia ncepe cu funcionarea mainii M0. Dac M0 se oprete atunci poate continua eventual funcionarea conform altei maini din M. Dac M0 se oprete cu capul de citire / scriere pe caracterul a atunci exist urmtoarele situaii : (M0, a) este nedefinit, n acest caz se oprete; (M0, a) = M', n acest caz funcionarea continu cu starea iniial a mainii M'.

Acelai mod de nlnuire va avea loc i la oprirea (dac intervine) mainii M'. n mod formal acest gen de compunere de maini Turing poate s fie descris n modul urmtor. Fie M = {M0, .., Mk}, k 0 astfel nct Mi = (Qi, T, mi, si), 0 i k. Fie q0, ..., qk stri care nu apar n mulimile Qi, 0 i k. Dac (M, , M0) este o schem de main Turing , ea va reprezenta maina MT = (Q, T, m, s) unde Q = Q0 ... Qk {q0, ..., qk} s = s0 m este definit n modul urmtor: a. dac q Qi, 0 i k, a T i mi(q,a) = (p, b), p h atunci m(q, a) = mi(q, a) = (p, b); b. dac q Qi, 0 i k, a T i mi(q, a) = (h, b) atunci m(q, a) = (qi, b); c. dac (Mi, a) (0 i k, a T) este nedefinit atunci m(qi, a) = (h,a); d. dac (Mi, a) = Mj (0 i k, a T) i mj(sj, a) = (p, b) atunci (p,b) p h / m(qi, a) = \ (qj, b) p = h Se observ c strile noi q0, ..., qk au fost introduse ca puncte de trecere de la o main la alta. Din definiie rezult c fiecare main funcioneaz "normal" pn cnd se oprete. Dac o main se oprete i este definit maina urmtoare se va trece n starea care face legatura cu maina urmtoare. Dac nu este definit maina urmtoare, MT se va opri. Dintr-o stare de legatur se intra n funcionarea mainii urmtoare pe baza simbolului curent de pe banda de intrare. S considerm de exemplu mulimea M = {M0} cu M0 = R = ({q}, T, m, q). Definim funcia n modul urmtor : (M0, a) = M0 dac a # (M0, #) este nedefinit n acest caz (M, , M0) reprezint o main notat cu R#, R# = ({q, q0}, T, m, q) unde m(q, a) = (q0, R), a T m(q0, a) = (q0, R), a # m(q0, #) = (h, a)

67

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

68

Se observ c maina se deplaseaz la dreapta pn la primul simbol #. Dac T = {a, b. c} putem s reprezentm maina R# sub forma :
a ---\ / /| \/ / | >R< | b /\ \ | / \ \| ---c

n cele ce urmeaz vom reprezenta grafic compunerea mainilor Turing utiliznd o serie de reguli : fiecare main Mi M apare o singur dat; maina iniial (M0) este indicat prin semnul >; dac a T i (Mi, a) este definit i de exemplu M' = (Mi,a) atunci va exist un arc de la Mi la M' etichetat cu a.

Se poate ntmpla ca n M s apar mai multe copii ale aceleiai maini (fiecare cu strile ei proprii diferite de strile celorlalte). n acest caz fiecare dintre exemplare reprezint o alt main Turing deci va fi desenat separat. n reprezentrile grafice urmtoare vom utiliza o serie de simplificri. De exemplu schema :
a ---------/ b \ > R ----------> R \ c / | ---------- | \ # / ------------

peste alfabetul T = {a, b, c, #} poate s fie reprezentata

a,b,c,# > R --------- R sau > R -- R sau RR sau R2 indicnd faptul c se fac dou deplasri la dreapta indiferent de coninutul benzii de intrare. Dac a T, a reprezint orice simbol din T diferit de a. Deci maina care caut simbolul # la dreapta poate s fie reprezentat ca :
/| /| >R< | \| \| /| /| > R < | # \| \|

a # sau

Urmtoarea schem:

68

Irina Athanasiu
/| /| >R< | # | \| | \| | |a # La

10/4/2003

Limbaje formale si translatoare

69

caut mergnd la dreapta un simbol diferit de #, cnd l gsete l copiaz la stnga poziiei pe care l-a gsit. Se observ c din notaia a # rezult c simbolul gsit, i care este diferit de #, este notat generic cu a i poate s fie utilizat n continuare. n cele ce urmeaz utilizm urmtoarele notaii : R#, este maina care caut primul simbol # la dreapta L#, este maina care caut primul simbol # la stnga R#, este maina care caut primul simbol diferit de # la dreapta L#, este maina care caut primul simbol diferit de # la stnga

Utiliznd aceste maini "simple" s construim o maina de copiere C care funcionez n modul urmtor. S presupunem c pe banda de intrare se gsete un ir w care nu conine simboli # (eventual irul poate s fie i vid). Presupunem ca la stnga irului de intrare se gsete un singur simbol #; pe banda de intrare nu se mai gsesc simboli diferii de # care s nu fac parte din w. Capul este poziionat pe simbolul # care marcheaz sfritul irului w. Evoluia mainii trebuie s fie (s, #w#) |-* (h, #w#w#). Se spune ca maina transform irul #w# n #w#w#. Reprezentarea grafic pentru aceasta main este :
+-------------------------+ | x # | -->R --------#R# 2x L# 2 x ---+ # | R#

>L#

S urmrim evoluia mainii pentru coninutul benzii #abc#


(q, #abc#) |-* (q, #abc#) |- (q, #abc#) |- (q, ##bc#) R # L# |- (q,##bc##) |- (q,##bc#) R# R# |- (q, ##bc#a#) |- (q, ##bc#a#) |- (q, ##bc#a#) L# x L# |- (q, #abc#a#) |- (q, #abc#a#) |- (q, #a#c#a#) x R # |- (q, #a#c#a#) |- (q, #a#c#a#) R# R# |- (q, #a#c#ab#) |- (q, #a#c#ab#) x L# |- (q, #a#c#ab#) |- (q, #abc#ab#) x L# |- (q, #abc#ab#) |- (q, #ab##ab#) R # |- (q, #ab##ab#) |- (q, #ab##abc#) x R#R# |- (q, #ab##abc#) |- (q,#abc#abc#)

69

Irina Athanasiu

10/4/2003
L#L# x |- (q, #abc#abc#) |- (q,#abc#abc#) R R# |- (h,#abc#abc#)

Limbaje formale si translatoare

70

n evolutia prezentat anterior starea nu conteaz aa c a fost notat cu un simbol generic q. Se observ c dac C ncepe s funcioneze cu un coninut al benzii de forma #u#v#w# la sfritul execuiei se obine pe banda #u#v#w#w#. C nu funcioneaz corect dac la pornire la dreapta capului de citire se gsete un simbol diferit de #. Maina SL :
+----------------+ | x # | >L ->R ----> LxR ----+ # |# L#

transform irul #w# n w#. Similar se poate construi o maina SR care transform irul #w# n ##ww#. Fie T0 = T - {#} cu f : T0* T0* astfel nct f(w) =wwR, f poate s fie calculat de urmtoarea main:
+--------------------+ | x # | >L ----> #R# xL# x ----+ |# R#

Pe parcursul funcionrii maina transform iruri de forma #x1 ... xn# n #x1 ... xi ... xnxnxn1 ... xi+1#, i = n-1, ..., 0. Pentru i = 0 se ajunge la #x1 ... xnxn ... x1#.

1.3.3.2. Extensii pentru maina Turing


Avnd n vedere simplitatea deosebit a funcionrii unei msini Turing standard, se pune problema dac aceasta nu poate s fie fcut mai "puternic": prin adaugarea unor extensii care s o apropie eventual de un calculator real. Se poate demonstra c adugarea unor faciliti ca de exemplu : banda de intrare infinit la ambele capete; mai multe capete de citire / scriere; mai multe benzi de intrare; o banda de intrare organizat n dou sau mai multe dimensiuni (eventual o memorie aa cum apare la calculatoare);

nu crete puterea de calcul oferit. Adic, nu se schimb nici clasa funciilor care pot s fie calculate i nici a limbajelor acceptate sau decise. Demonstratiile de echivalen sunt constructive realizndu-se pentru fiecare extensie construirea unei maini Turing standard capabil s simuleze funcionarea unei maini Turing avnd extensia considerat. S considerm de exemplu o maina Turing care are o band

70

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

71

infinit la ambele capete. Schimbarea definiiei formale pentru acest model de maina Turing intervine n modul n care se definete noiunea de configuraie i relaia |- asupra configuraiilor. n acest caz o configuraie este de forma (q, w, a, u) i w nu incepe cu un simbol # iar u nu se termina cu un simbol #. Nu mai exist limitri referitoare la deplasarea la stnga i deci dispar noiunile de stare i respectiv de configuraie de agare. Propoziie. Fie M1 = (Q1, T1, m1, q1) o main Turing cu banda de intrare infinit la ambele capete. Exist o main Turing standard M2 = (Q2, T2, m2, q2) astfel nct, pentru orice w (T1 - {#})* sunt ndeplinite urmtoarele condiii : dac M1 se oprete pentru w, adic:
(q1, w#) |-* (h, uav), u, v T1*, a T1

atunci i M2 se oprete pentru w, adic:


(q2, #w#) |-* (h, #uav), u, v T1*, a T1

dac M1 nu se oprete pentru w atunci nici M2 nu se oprete pentru w. Demonstratie. Banda de intrare pentru M2 se obine prin ndoirea benzii de intrare a mainii M1. Adic, dac considerm c banda de intrare M1 are un "mijloc" ales arbitrar :
---------------------------------------| -3 | -2 | -1 | 0 | 1 | 2 | 3 | ----------------------------------------

atunci banda de intrare pentru M2 va avea forma:


+--------------------------| | 0| 1| 2| 3| | $ |----+----+----+----| | | -1 | -2 | -3 | -4 | +---------------------------

n simulare se va consider deci c funcionarea masini M1 n partea dreapta a benzii de intrare corespunde funcionrii maini M2 pe pista superioar a benzii sale de intrare, respectiv funcionarea maini M1 n partea stng corespunde funcionrii maini M2 pe pista inferioar a benzii sale de intrare. Rezult deci c pentru M2 se va utiliza un alfabet care conine perechi de simboli din alfabetul T1. O astfel de pereche (a, b) va indica faptul c a este coninut de pista superioar iar b este coninut de pista inferioar. Vom nota cu T o mulime definit n modul urmtor :
T = {a | a T1}

n acest caz T2 = {$} T1 (T1 x T1) (T1 x T) (T x T1). M2 simuleaza M1 n modul urmtor : 1. se mparte banda de intrare n dou piste i se copiaz irul de intrare pe pista superioar; 2. se simuleaz funcionarea M1 pe banda obinut;

71

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

72

3. cnd i dac M1 se oprete, se reface forma iniial a benzii. Pentru a realiza prima etapa trebuie s se realizeze o prelucrare de iruri. Adic, dintr-o banda de intrare de forma :
---------------------------------------| # | a1 | a2 | ...| an | # | # | ---------------------------------------

trebuie s se ajung la un coninut al benzii de forma :


+-----------------------------------| | a1 | a2 | ...| an | # | | | $ |----+----+----+----+----| # | | | # | # | ...| # | # | | +-----------------------------------

unde a1, ..., an (T1 - {#})*. Se observ c prelucrrile necesare nu sunt deosebit de dificile. Etapa a doua poate s fie realizata de ctre o maina M1' care are n mulimea sa de stri pentru fiecare q Q1 o pereche de stri notate <q, 1> i <q, 2>. Dac M1' este ntr-o stare <q, 1> nseamn c M1' acioneaz asupra pistei superioare a benzii de intrare. Dac M1' este n starea <q, 2> atunci nseamn c M1' acioneaz asupra pistei inferioare. De asemenea exist strile <h, 1> i <h, 2> care reprezint oprirea n situaia n care M1' lucra pe pista superioar respectiv inferioar. Funcia de tranziie m' pentru M1' este definit n modul urmtor : a) dac q Q1, (a1, a2) T1 x T1 i m1(q, a1) = (p,b) atunci
/ (<p, 1>, L) dac b = L m1'(<q,1>,(a1,a2) = (<p, 1>, R) dac b = R \ (<p, 1>, (b, a2)) dac b T1

b) dac q Q1, (a1, a2) T1 x T1 i m1(q, a2) = (p, b) atunci


/ (<p, 2>, R) dac b = L m1'(<q,2>,(a1,a2) = (<p, 2>, L) dac b = R \ (<p, 2>, (a1, b)) dac b T1

c) dac q Q1 {h} atunci


m1'(<q, 1>, $) = (<q, 2>, R) m1'(<q, 2>, $) = (<q, 1>, R)

d) dac q Q1 {h} atunci


m1'(<q, 1>, #) = (<q, 1>, (#, #)) m1'(<q, 2>, #) = (<q, 2>, (#, #))

e) dac a1, a2 T1 atunci

72

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

73

m1'(<h, 1>, (a1, a2)) = (h, (a', a2)) m1'(<h, 2>, (a1, a2)) = (h, (a1, a'))

f) pentru situaiile care nu se ncadreaz n nici unul dintre cazurile anterioare m1' se definete arbitrar. Se observ c n cazurile a i b este descris funcionarea mainii M1 la dreapta i respectiv la stnga "mijlocului" ales. Cazul c. trateaza comutarea ntre piste care trebuie realizat atunci cnd se ajunge la limita din stnga a benzii. Cazul d. indic modul n care se face extinderea celor doua piste la dreapta. Cazul e trateaza intrarea n starea de oprire (h) a maini simulate M1. Se observ ca la intrarea n aceasta stare se va produce intrarea n starea h i a mainii M1' cu inregistrarea pistei pe care s-a facut oprirea mainii simulate. Dac banda de intrare a masini M1 conine irul w (T1 - {#})* i aceasta se oprete cu un coninut de forma :
----------------------------------------------| # | b1 | b2 | ...| bi | ...| bn | # | # | -----------------------------------------------

atunci M1' se va opri cu un coninut de forma :


+------------------------------------| | ck+1 | ck+2 | ... | c2k | | | $ |------+------+-----+-----| # | | | ck | ck-1 | ... | c1 | | +-------------------------------------

unde c1c2 ... c2k = # ... # b1b2 ... bi-1 b bi+1 ... bn # ... # cu bi #, 1 i n. Pentru etapa a treia se face translatarea simbolilor diferii de # de pe pista inferioar pe pista superioar :
+------------------------------------------| | b1 | b2 | ... | bi | ... | bn | | | $ |----+----+-----+----+-----+----| # | | | # | # | ... | # | ... | # | | +------------------------------------------

Din nou aceasta prelucrare este simpl. n final se reface banda sub forma :
+------------------------------------------| # | b1 | b2 | ... | bi | ... | bn | # | +------------------------------------------

Rolul alfabetului T utilizat n construirea mainii M1' este de a permite identificarea poziiei capului la oprirea mainii M1'. Similar definitiei din cazul masinilor Turing standard putem s considerm i n acest caz definiia notiunii de calcul. i anume dac T1 i T2 sunt doua mulimi de tip alfabet care nu conin simbolul # atunci spunem c funcia f : T1* T2* este calculat de maina Turing, M care are banda de intrare infinit la ambele capete, dac i numai dac pentru orice w T1*, dac f(w) = u atunci (q, w#) |-* (h,u#). De asemenea noiunile de acceptare respectiv de

73

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

74

decidabilitate referitoare la limbaje pot s fie definite pentru masinile Turing cu banda infinit la ambele capete ntr-o maniera similara celei de la maina Turing standard. Orice funcie care este calculat i orice limbaj care este acceptat sau decis de o maina Turing cu banda infinit la ambele capete este calculat respectiv acceptat sau decis de o main Turing standard. Construcii i rezultate similare pot fi realizate i pentru celelalte extensii considerate la inceputul acestui subcapitol. Din acest motiv n tratarea pe care o vom realiza n continuare putem s considerm pentru a simplifica demonstraiile n loc de maini Turing standard maini care au oricare dintre extensiile amintite sau chiar combinaii ale acestora. Extinderea masini Turing se poate face i prin renunarea la caracterul determinist al acestora. Pentru o main Turing nedeterminist funcia m este definit n modul urmtor : m : Q x T P((Q {h}) x (T {L, R})) Dupa cum s-a aratat pentru orice automat finit nedeterminist se poate construi un automat finit determinist echivalent. n cazul automatelor push down aceasta echivalenta nu exist. Cu alte cuvinte automatele push down nedeterministe sunt "mai puternice" dect cele deterministe deoarece automatele push down nedeterministe accepta o clasa mai larga de limbaje. n cazul masinilor Turing nedeterministe deoarece pentru acelai ir de intrare se pot obine rezultate diferite, se pune problema cum se alege "calculul util" efectuat de maina Turing. Vom restringe puin problema considernd numai noiunea de acceptare. n acest caz ceea ce conteaz este c maina Turing se oprete n una din evoluiile sale posibile. Rezultatul depus pe band nu este n acest caz neaprat semnificativ. S considerm mai nti un exemplu de main Turing nedeterminist. Fie limbajul
L = { w { a, b}* | w contine sirul abaab}

Evident, limbajul este de tip regulat i poate s fie acceptat de un automat finit determinist. O soluie de maina Turing nedeterminista care accepta acest limbaj este :
a, b -\/ b a a b a /| >L -----> L ----> L ----> L ----> L ----> a R | # | | | | | | \| #| b,# | b,# | a,# | b,# | #| -------->------>-------<--------<-------| | /| # | \|

Configuratia din care se pleaca este (q, #w#). Maina Turing pornete spre stnga. La un moment dat, la ntlnirea unui simbol b, maina Turing "ghicete" ca a gsit sfritul subirului cutat. Dac ghicirea este corect atunci maina se va opri, altfel maina nu se oprete. Find vorba de o funcionare nedeterminist tot ce conteaz este c dintre toate soluiile posibile exist una pentru care maina se oprete. Se poate demonstra urmtoarea propoziie. Propoziie Pentru orice maina Turing, M1 nedeterminist exist o maina Turing M2 determinist (standard) astfel nct pentru orice ir w care nu conine simbolul # : i) dac M1 se oprete pentru w atunci i M2 se va opri pentru w; i) dac M1 nu se oprete pentru w atunci nici M2 nu se oprete pentru w.

74

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

75

S considerm o schi de demonstraie pentru propoziia anterioar. Fie M1 = (S, T1, m, s). M2 trebuie s ncerce toate evoluiile posibile pentru M1 n cutarea unei evoluii pentru care M1 se oprete. M1 poate avea ns un numr infinit de evoluii pornind din s i avnd un ir w pe banda de intrare ( s nu uitm c dac irul nu este acceptat de M1 aceasta nu se va opri). Se pune problema cum trebuie s fac M2 cutarea ntre aceste evoluii (n ce ordine ?). Ideea este urmtoarea, dac M1 este n configuraia C atunci exist mai multe configuraii C' astfel nct C |- C'. Numrul configuraiilor C' este ns finit i depinde numai de definiia funciei m (nu de configuraia C). Dac starea curenta este q i simbolul curent la intrare este a, atunci m(q, a) P((Q {h}) x (T {L, R})) este o mulime finit, deoarece |m(q,a)| (|Q| + 1) x (|T| + 2). Fie
r = max (|m(q,a)|) qQ aT

Valoarea r rezult din definiia funciei m i reprezint numrul maxim de configuraii urmtoare posibile pentru o configuraie dat. Deci dac pornim din configuraia iniial C = (q,#w#), M1 poate s treac n maximum r configuraii urmtoare diferite. Fiecare dintre aceste r configuraii diferite poate s treac la rndul ei n alte r configuraii diferite. Rezult deci c pentru o evoluie n k pai se poate ajunge la un numr de maximum rk configuraii diferite pornind din configuraia iniial. Pentru fiecare mulime m(q, a), q Q, a T, considerm cte o ordonare arbitrar a elementelor care o compun. M2 va analiza n mod sistematic nti toate configuraiile n care se poate ajunge ntr-un pas, apoi n doi pai, etc. Dac n aceasta cutare se trece printr-o configuraie pentru care M1 se oprete se va opri i M2. Dac M1 se oprete vreodat atunci ea se oprete ntr-un numr finit de pai. Corespunztor M2 va descoperi aceasta oprire ntr-un numr finit de pai. Maina M2 poate s fie construit avnd trei piste. O pist este utilizat ca martor, pe ea se pastreaz irul iniial. A doua pist este utilizat pentru a simula funcionarea maini M1. Fiecare simulare ncepe cu o copiere a coninutului primei benzi (partea util) pe a doua band. A treia band pstreaz evidena incercrilor fcute. i anume pe aceast band se gasete un ir dintr-un alfabet D = {d1, ..., dr}, unde r este numrul maxim de configuraii urmtoare posibile pentru orice configuraie a maini M1. Pe aceasta band se vor genera iruri care codific modul n care se aleg alternativele posibile n fiecare pas al simulrii. Astfel, un ir de forma d3 d5 d1 indic faptul c se va ncerca un calcul n trei pai. n primul pas se alege dac exist a treia alternativ din cele maximum r posibile, n al doilea pas se alege a cincea alternativ iar n al treilea pas se alege prima alternativ posibil. Dac n aceasta alegere nu exist o altenativ cu numrul celei indicate se abandoneaz calculul. Generarea irurilor pe a treia band se face n ordine lexicografic. Dupa fiecare ncercare care nu a dus la oprire se va terge coninutul celei de a doua benzi i se genereaz un nou ir pe a treia band. Dac ncercarea duce la oprirea masini simulate se oprete i M2. Se observ c toate prelucrrile descrise anterior sunt prelucrri simple asupra unor iruri de simboli ce pot s fie realizate de ctre masini Turing standard. Pe baza propoziiei enunate anterior rezult ca orice limbaj acceptat de o main Turing nedeterminist va fi acceptat i de o maina Turing determinist.

1.3.3.3. Automate liniar mrginite

75

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

76

Un automat liniar mrginit este un caz particular de main Turing nedeterminist. Definiia unui astfel de automat este: ALM = (Q, T, m, s, F) unde: Q este o mulime finit de stri T este alfabetul benzii de intrare, #, L, R T m este funcia de tranziie m : Q x T P(Q x (T {L, R})). s Q este starea iniial pentru automatul liniar mrginit. F Q este mulimea strilor finale Dac q Q este o stare, a T este un simbol de pe banda de intrare i (p, b) m(q, a) nseamn c din starea curent q pentru simbolul de intrare a se poate trece n starea p, nlocund sibmbolul de pe banda de intrare sau efectund o micare la stnga sau la dreapta. Definiia este a unui acceptor nedeterminist. Funcionarea automatului pornete cu o configuraie avnd pe banda de intrare un ir cuprins ntre doi simboli # (dou blancuri). Deoarece funcia de tranziie nu este definit pentru simbolul #, nseamn c spaiul de micare al capului de citire/scriere pe banda d intrare este limitat la lungimea iniial a irului de intrare. Cu alte cuvinte dac printr-o deplasare la stnga sau la dreapta capul de citire/scriere ajunge n afara spaiului ocupat iniial de ctre irul analizat automatul se oprete. Conform definiiei, pentru automatele liniat mrginite se consider o acceptare prin stari finale. Dac la oprirea automatului capul de citire se gsete la captul din dreapta al irului i starea automatului face parte din F nseamn c evoluia automatului a dus la acceptare. Se poate demonstra c pentru orice gramatic dependent de context exist o gramatic echivalent liniar mrginit. Produciile unei gramatici n liniar mrginit au n partea dreapt cel mult doi simboli. Dac exist o producie S AB (unde S este simbolul de start al gramaticii) atunci A = S. Pentru orice gramatic dependent de context liniar mrginit se poate construi un automat liniar mrginit care accept acelai limbaj. De asemenea pentru orice automat liniar mrginit este posibil s se construiasc o gramatic dependent de context care genereaz acelai limbaj. Adic, clasa limbajelor acceptate de automate liniar mrginite este clasa limbajelor dependente de context. Intuitiv, relaia de echivalen dintre gramaticile dependente de context i automatele liniar mrginite este susinut de condiia pe care o satisfac produciile unei gramatici dependente de context. i anume - dac A este o producie atunci |A| ||. Adic orice ir din limbajul generat de ctre gramatic este mai lung cel puin egal cu orice form propoziional obinut n secvena de derivri prn care se obine irul respectiv. Se poate construi i o definiie de automat liniar mrginit determinist. Automatele liniar mrginite nedeterministe sunt mai puternice dect cele deterministe, n sensul c existe limbaje acceptate de ctre automate liniar mrginite nedeterministe dar care nu sunt acceptate de automate liniar mrginite deterministe. n particular limbajele independente de context sunt acceptate i de automatele liniar mrginite deterministe (acceptoarele obinuite pentru limbajele independente de context sunt automatele cu stiv).

1.3.3.4. Relaia ntre maina Turing i gramatici


Propoziie. Fie M = (Q, TM, m, q) o main Turing. Exist o gramatic G = (N, TG, P, S) astfel nct pentru orice pereche de configuraii (q, uav) i (q', u'a'v') ale maini Turing
* (q, uav) |- (q', u'a'v')

76

Irina Athanasiu
M

10/4/2003

Limbaje formale si translatoare

77

dac i numai dac


* [uqav] [u'q'a'v'] G

Demonstratie. Se observ c formele propoziionale ce se obin n gramatica G conin iruri care corespund configurailor maini Turing. Astfel, pentru o configuraie de forma (q,u,a,w) se obine o form propoziional [uqaw]. Poziia pe care o ocupa simbolul corespunztor strii indic de fapt poziia capului de citire pe banda de intrare. Mulimea simbolilor terminali pentru G este TG = TM {[, ]}. Mulimea simbolilor neterminali N = Q {h, S}. Mulimea produciilor se construiete n modul urmtor : i) q Q, a TM dac m(q,a) = (p, b) b T atunci qa pb P i) q Q, a TM dac m(q,a) = (p, R) atunci qab apb P pentru b TM i qa] ap# P iii) q Q, a TM dac m(q,a) = (p, L) atunci dac a # sau c ] atunci bqac pbac P, b TM, c TM {]} dac a = # atunci bq#] pb] P, b TM. Se observ c n construcia anterioara simbolul de start al gramatici nu joac nici un rol. n toate produciile se observ ca apare cte un singur neterminal att n partea dreapta ct i n partea stnga. Acest neterminal corespunde unei stri. Poziia sa n cadrul fiecrui ir reprezint de fapt poziia capului de citire. Simbolul de start al gramaticii nu este utilizat. Se poate demonstra utiliznd aceast construcie c : (q, u, a, v) |- (q', u', a', v') dac i numai dac [uqav] [u'q'a'v'] Demonstraia se realizeaz considernd toate formele posibile rezultatul se extinde natural pentru nchiderile acestor relaii. S considerm de exemplu maina Turing M = ({q0, q1, q2}, {a, #}, m, q0) pentru care m este definit n modul urmtor :
m(q0, m(q0, m(q1, m(q1, m(q2, m(q2, a) #) a) #) #) a) = = = = = = (q1, (q0, (q2, (q1, (h, (q2, R) a) R) a) #) R)

de producii.

Mai

departe

77

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

78

s considerm pentru aceast main evoluia pentru configuraia (q0, #a#)


(q0, #a#) |- (q0, aa#) |- (q1, aa#) |-+ (h, aa#).

S construim gramatica corespunztoare : G = ({q0, q1, q2, h, S}, {q, #, [, ]}, P, S) P va conine urmtoarele producii : i) n cazul n care se face scriere pe banda
q0# q0 a ( corespunde m(q0, #) = (q0, a) ) q1# q1 a ( corespunde m(q1, #) = (q1, a) ) q2# h # ( corespunde m(q2, #) = (h, #) )

i) n cazul n care se fac deplasri dreapta


q0aa a q1 a ( corespunde m(q0, a) = (q1, R)) q0a# a q1 # q0a] a q1 #] q1aa a q2 a (corespunde m(q1, a) = (q2, R)) q1a# a q2 # q1a] a q2 # ] q2aa a q2 a (corespunde m(q2, a) = (q2, R)) q2a# a q2 # q2a] a q2 #]

Un calcul realizat de M poate s fie :


(q0, #) |- (q0, a#) |- (q1, a#) |- (q1, aa# |- (q2, aa#) |- (h, aa#)

O derivare n G care pornete din irul [q0#] este :


[q0#] [q0a] [aq1#] [aq1a] [aaq2#] [aah#]

Se observ c n aceasta derivare simbolul de start al garamtici nu a intervenit. Gramatica este n acest caz utilizat ca mecanism de specificare a unor substituii de iruri i nu ca generator de limbaj. Aa cum o main Turing a fost tratat ca acceptor de limbaj o gramatica poate s fie privit ca un dispozitiv capabil s reprezinte (efectueze) calcule. Fie T1 i T2 dou mulimi de tip alfabet care nu conin simbolul # i fie f : T1* T2*, spunem c f este calculabil gramatical dac i numai dac exist o gramatica G = (N, T, P, S) astfel nct T1, T2 T i exist irurile x, y, x', y' (N T)* care indeplinesc urmtoarea condiie pentru u T1* i v T2* v = f(u) dac i numai dac xuy * x'vy'. n acest caz

78

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

79

se spune c G calculeaz funcia f. De la iruri definiia se poate extinde la numere naturale ntr-o manier similar celei utilizate la maina Turing. S considerm de exemplu T1 = {a, b} i f : T1* T1*, f(w) = wR. Funcia f este calculabil de ctre gramatica G = (N, T, P, S} unde N = {A, B, S}, T = {a, b, *, [, ]} iar P conine urmtoarele producii :
1. [a [A,[b [B 2. Aa aA, Ab bA, Ba aB, Bb bB 3. A* *a, B* *b

irurile x, y, x' i y' sunt [, *], [* i respectiv ]. G transform un ir de forma [w*] cu w {a, b}* n modul urmtor. Se transform nti primul simbol (a sau b) cu care ncepe irul n A sau B utiliznd una dintre produciile [a [A sau [b [B. n continuare neterminalul astfel obinut migreaz spre limita din dreapta a irului. La ntlnirea simbolului * se aplic una dintre produciile A* *a sau B* *b. De exemplu pentru irul abb se obine :
[abb*] [Abb*] [bAb*] [BAb*] [BbA*] [Bb*a] [bB*a] [b*ba] [B*ba] [*bba]

Se observ c nu este semnificativ ordinea n care se aplic produciile. Propoziie Orice funcie calculabil n sens Turing este calculabil i gramatical. Demonstraia acestei propoziii este constructiv, adic pornind de la o maina Turing se construiete o gramatic care realizeaz acelai calcul. Din rezultatele prezentate putem trage concluzia echivalenei ntre gramaticile de tip 0 (fr restricii) i mainile Turing din punctul de vedere al limbajelor acceptate (generate) i al puterii de calcul. Considernd echivalena dintre gramatici i masinile Turing se pune intrebarea cum se poate construi o main Turing care s accepte limbajul generat de o gramatica G = (N, T, P, S). Avnd n vedere ca operaia de derivare presupune de fapt prelucrri simple de iruri de simboli, se poate construi o main Turing care s execute operaia de derivare. O astfel de main se poate obine de exemplu utiliznd cte o main Turing pentru fiecare producie. Avnd n vedere modul n care se obine un ir care face parte din L(G) se poate construi o main Turing eventual nedeterminist care s realizeze aceleasi operaii.

79

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

80

1.3.3.5. Elemente de calculabilitate


Discuia coninut n acest subcapitol depaeste cadrul limbajelor formale dar este important pentru a realiza legatura dintre modelele de calcul considerate i lumea real a calculatoarelor, mai ales pentru a oferi o caracterizare a posibilitilor oferite de acestea. n momentul n care s-a dat definiia limbajelor s-a precizat faptul c numai o anumit parte a acestora poates fie descris ntr-o form finit. Gramaticile, automatele finite, automatele push down, maina Turing sunt astfel de reprezentri finite. Se pune problema dac odat cu maina Turing s-a atins ntr-adevr limita de reprezentare finit a limbajelor. De asemenea, avnd n vedere c o gramatica poate s fie interpretat i ca un dispozitiv capabil s efectueze calcule, se pune intrebarea dac nu exist mecanisme mai puternice de reprezentare dect gramaticile i maina Turing (avnd n vedere faptul c un calculator real pare mult mai puternic dect o maina Turing). Maina Turing Universal Spre deosebire de o maina Turing standard, modelul Von Neumann de calculator presupune noiunea de program memorat. Ar apare aici o diferen important ntre o maina Turing i un calculator real. i anume o main Turing standard este dedicat rezolvrii unei anumite probleme (calculului unei anumite funcii) n timp ce un calculator este un dispozitiv universal, capabil s treac la calculul unei noi funcii prin schimbarea programului, deci a ceva coninut n memorie, fr a schimba ns modul de funcionare a unitii de control. Se pune intrebarea dac nu se poate construi o maina Turing care s funcioneze ntr-o manier similar adic, s primeasca la intrare att irul care se transform ct i o descriere a transformrii. O astfel de main Turing se numete maina Turing universal. Pentru a construi o main Turing universal este necesar s obinem nti un mod de descriere al unei maini Turing sub forma de ir astfel nct aceast descriere s poat s fie utilizat ca intrare pentru o alta main Turing . Fiecare main Turing este definit utiliznd patru elemente MT = (Q, T, m,s). Deoarece Q i T sunt mulimi finite descrierea unei maini Turing poate s fie fcut sub forma unui ir utiliznd simboli din Q, T, paranteze, virgule i alte semne de punctuaie. O asemenea reprezentare sub forma de ir, nu este recomandabil deoarece avem nevoie pentru maina pe care o construim de un alfabet finit pe care s l utilizm n definiia acesteia, alfabet care s permit reprezentarea oricrui alfabet posibil pentru o main Turing. Vom consider ca exist mulimile infinit numrabile : Qinf = {q1, q2, ...} i Tinf = {a1, a2, ...}. astfel nct pentru orice main Turing, mulimea strilor i respectiv alfabetul de intrare sunt submulimi finite din Qinf i respectiv Tinf. Se consider urmtoarea codificare pentru elementele care aparin unei definiii de main Turing utiliznd un alfabet ce conine un singur simbol {I} :
element | cod(element) ---------+-------------| Ii+1 qi ---------+-------------h |I ---------+-------------L |I

80

Irina Athanasiu
---------+-------------R | II ---------+-------------| Ii+2 ai ------------------------

10/4/2003

Limbaje formale si translatoare

81

Se observ c fiecare stare q Q {h} are un cod unic, acelai lucru este valabil i pentru fiecare simbol din alfabetul de intrare. Fie c un simbol c I. Pentru construirea irului care descrie o main Turing se utilizeaz numai simbolii c i I. Fie MT = (Q, T, m, s) o main Turing cu Q Sinf i T Tinf. Deci Q = {qi1, qi2, ..., qik}, i1 < i2 < ... < ik, iar T = {aj1, aj2, ... ajl}. Construim kl iruri notate cu Spr, unde 1 p k i 1 r l. Fiecare ir Spr codific valoarea funciei de tranziie pentru o pereche (qip, ajr). Fie de exemplu m(qip, ajr) = (q', b), q' Q {h} i b T {L, R} atunci Spr = cw1cw2cw3cw4c unde :
w1 w2 w3 w4 = = = = cod(qip) cod(ajr) cod(q') cod(b).

Notm cu codif(M) irul cS0cS11S12 ... S1lS21 ... S2l ... Sk1 Sk2 ... Skl c. S0 este codificarea strii initiale, S0 = cod(s). Se observ c irul astfel obinut reprezint o codificare unic pentru o maina Turing. De asemenea pe baza unui astfel de ir se poate reconstrui descrierea "clasica" a mainii. S considerm de exemplu MT = (Q, T, m,s) cu Q = {q2}, T = {a1, a3, a6}, s = q2 i m(q2, a3) = m(q2, a6) = (q2, R) i m(q2, a1) = (h,a3). Utiliznd notaiile anterioare, rezult k = 1, i1 = 2, l = 3 i j1 = 1, j2 = 3, j3 = 6. Se obine :
S11 | m(q2, a1) = (h, a3) | cIIIcIIIcIcIIIIIc -----+---------------------+----------------------S12 | m(q2, a3) = (q2,R) | cIIIcIIIIIcIIIcIIc -----+---------------------+----------------------S13 | m(q2, a6) = (q2, R) | cIIIcIIIIIIIIcIIIcIIc

Rezult
codif(M) = cI3c|cI3cI3cIcI5c|cI3cI5cI3cI2c|cI3cI8cI3cI2c|c

O main Turing universal U primete pe banda de intrare un ir de tip codif(M) i un ir w pe care trebuie s funcioneze M. irul w trebuie s fie i el codificat utiliznd alfabetul {c, I}. Codificarea se face n modul urmtor. Dac w = b1 ... bn, cu bi Tinf atunci:
codif(w) = c cod(b1) c cod(b2) c ... c cod(bn) c.

Se observ c irul obinut codif(w) nu poate s conin simboli #, chiar dac w conine simboli #. U = (Qu, {I, c, #}, mu, qu) trebuie s satisfaca urmtoarele condiii - pentru orice main Turing , M = (Q, T, m, s) : 1. dac (h, uaw) este o configuraie de oprire pentru M astfel nct (s, #w#) |-*M (h, uav) atunci, (qu, #codif(M) codif(w) #) |-*U (h, #codif(uav)#)

81

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

82

2. dac (qu, #codif(M)codif(w)#) |-*U (h,u'a'v') pentru o configuraie de oprire (h, u'a'v') pentru U atunci a' = #, v' = , u' = #codif(uav) pentru u, a, v astfel nct (h, uav) este o configuraie de oprire pentru M i (s, #w#) |-*M (h, uav). Adic dac M se oprete pentru w atunci i U se oprete pentru un ir obinut prin concatenarea irurilor codif(M) i codif(w). Mai mult, pentru o astfel de oprire coninutul benzii U reprezint o codificare a rspunsului masini Turing, M pentru w. De asemenea dac U se oprete pentru un ir care reprezint codif(M)codif(w) atunci i M se va opri pentru w i rezultatul lasat de U reprezint codificarea rezultatului lsat de M. Pentru a simplifica discutia vom consider o variant U' a maini U, variant care utilizeaz trei benzi. Conform celor menionate anterior pentru aceasta variant se poate construi o main Turing echivalent cu o singur band. Prima band va conine iniial codif(M)codif(w), a doua band conine n timpul simulrii codif(M) iar a treia band va conine codificarea strii curente a maini M care se simuleaz. Funcionarea ncepe cu prima band coninnd codif(M)codif(w), celelalte benzi find goale. U' va copia irul codif(M) pe a doua band i va modifica coninutul primei benzi la forma #c codif(#w#). Se observ c localizarea nceputului irului codif(w) n irul iniial se face uor pentru c aici exist trei simboli c consecutivi. Din codif(M) se identific S0 (codul pentru starea iniial) i se copiaz pe cea de a treia band. n continuare U' ncepe s simuleze funcionarea maini Turing M. ntre paii de simulare cele trei capete de citire / scriere utilizate (exist trei benzi de intrare) sunt poziionate n modul urmtor : pentru prima band pe ultimul c care indic sfritul codului pentru simbolul curent parcurs de M; pentru a doua i a treia band la marginea stnga a benzilor respective.

n acest mod cnd M pornete s trateze ultimul simbol # din irul de intrare #w#, U' va ncepe simularea deplasndu-i capul pe ultimul simbol c de pe banda. U' va cuta pe a doua band un subir de forma ccIicIjcIkcIlcc unde Ii este irul coninut n a treia banda, iar Ij este irul curent de pe prima banda. La identificarea unui astfel de subsir U' se va mica corespunztor. Dac Il este codif(L) sau codif(R) atunci se realizeaz deplasarea pe prima banda de intrare la stnga respectiv la dreapta. Dac Il este cod(a) pentru a Tinf se observ c nlocuirea simbolului curent poate s presupun deplasarea coninutului primei benzi pentru ca spaiul ocupat de codul pentru a poate s fie diferit de cel ocupat de simbolul nlocuit. n cadrul aceleiai micri U' nlocuiete irul inscris n a treia band cu Ik. Dac acum coninutul acestei benzi este cod(h) U' va deplasa capul de pe prima banda pe primul simbol # aflat la dreapta poziiei curente dup care se oprete. Dac pe banda a treia nu se gsete cod(h) atunci se continu simularea. Rezult deci c o main Turing este suficient de puternic pentru a fi comparata cu un calculator real. De fapt o main Turing este echivalent cu noiunea intuitiv de algoritm. Mai mult conform ipotezei Church (Church's Thesis) nici o procedur de calcul nu este un algoritm dac nu poate s fie executat de o maina Turing. Acest rezultat care este acceptat, n prezent constituie numai o ipotez pentru c nu constituie un rezultat matematic, ci indic numai faptul c un anumit obiect matematic (maina Turing) este echivalent cu un concept informal. Revenind la problema reprezentri finite a limbajelor se pune problema cum arat limbajele care nu sunt Turing decidabile. Cu alte cuvinte putem s dm o reprezentare finit pentru un astfel de limbaj ?. Dac aa ceva este posibil nseamn c putem s construim un algoritm care s decid dac un ir face parte din limbajul respectiv. Conform ipotezei Church ns noiunea de algoritm i cel de maina Turing sunt echivalente, Rezult deci c ar exist o maina Turing

82

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

83

care s verifice dac irul face parte din limbaj, adica limbajul ar fii Turing decidabil ceea ce contrazice ipoteza. S discutm puin i relaia dintre limbajele Turing acceptabile i limbajele Turing decidabile. Se poate demonstra urmtorul rezultat: Propoziie. Orice limbaj L Turing decidabil este i Turing acceptabil. Demonstraie. Fie M o main Turing care decide L. Atunci se poate construi M' care s accepte L.
N /| >ML ----- N | \|

Se observ c M' simuleaz M dupa care studiaz rspunsul obinut pe band. Dac rspunsul este N, M' va intra ntr-un ciclu infinit. Se pune intrebarea care este raportul invers ntre limbajele acceptabile i cele decidabile Turing. Dac ar fi posibil ca pentru orice maina Turing i orice ir de intrare w, s prevedem dac maina Turing se va opri pentru w, atunci orice limbaj Turing acceptabil ar fi i Turing decidabil, deoarece dac M1 este maina Turing care accept L putem s construim M2 care decide L n modul urmtor. M2 va executa calculele necesare pentru o prevedea dac M1 se oprete pentru w. Corespunztor M2 se va opri cu un simbol D sau N pe banda de intrare dup cum M1 accept sau nu irul w. Rezult c cele doua probleme: este orice limbaj Turing acceptabil i Turing decidabil ? se poate construi o main Turing care s prevad pentru orice main Turing, M, dac aceasta se oprete sau nu pentru un ir, w ?

sunt echivalente. Am artat c dac se poate construi o main Turing care s prevad pentru orice main Turing dac aceasta se oprete sau nu pentru orice ir atunci orice limbaj acceptabil este i decidabil. S presupunem acum c orice limbaj acceptabil este i decidabil. n acest caz limbajul:
L0 = { codif(M)codif(w) | M accepta w}

care este acceptat de maina Turing universal, este un limbaj decidabil. Fie M+ maina Turing care decide acest limbaj. n acest caz M+ poate s prevad pentru orice main Turing dac aceasta se oprete sau nu pentru orice ir w. Vom arta n continuare c L0 nu este decidabil. n mod corespunztor rspunsul la cele doua probleme enuntate anterior este : NU. Dac L0 este Turing decidabil atunci limbajul :
L1 = { codif(M) | M accepta codif(M) }

este Turing decidabil. Dac M0 este maina care decide L0 atunci se poate construi maina M1 care s decid L1. Funcionarea M1 const din transformarea intrrii din #w# n #wcodif(w)# pe care va funciona apoi M0. Deci M1 va calcula acelai rezultat asupra irului #w# ca i M0 asupra irului #wcodif(w)#. Conform definiiei limbajului L0, M0 va scrie D pe banda dac i numai dac : a. w este codif(M) pentru o main Turing

83

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

84

b. maina Turing M, accept irul w, adic irul de intrare codif(M). Dar asta este exact definiia limbajului L1. Rezult c este suficient s artm c L1 nu este Turing decidabil. S presupunem c L1 este Turing decidabil n acest caz i limbajul
L1 = { w {I,c}* | w nu este codif(M) pentru nici o masin Turing sau w = codif(M) pentru o masina Turing, M, care nu accept sirul codif(M) }

este decidabil. O main Turing care decide L1 se obine din maina Turing care decide L1 inversnd la oprirea mainii rspunsurile D i N. Limbajul L1nu este ns Turing acceptabil. S presupunem c exist o maina Turing M* care accepta L1. Din definiia limbajului L1 rezult c: M, codif(M) L1 M nu accept codif(M) (1) dar, M* a fost construit pentru a accept L1, adic: codif(M*) L1 => M* accept codif(M*) (2) Din (1) i (2) rezult M* nu accept codif(M*) M* accept codif(M*) adica M* nu poate s existe, adic L1, L1 i deci L0 nu sunt Turing decidabile. Deoarece L0 nu este Turing decidabil nu exist un algoritm care s stabileasc dac o main Turing oarecare se oprete pentru un ir oarecare. Se observ c am gsit o problema pentru care nu avem o soluie sub form de algoritm. Astfel de probleme se numesc nedecidabile (nerezolvabile). De fapt L0 descrie cea mai cunoscut problema nedecidabila i anume problema opriri maini Turing. Enunul acestei probleme este : "s se determine pentru o main Turing M, arbitrar dac se oprete pentru un ir de intrare dat ". Alte probleme nedecidabile echivalente de fapt cu aceast problem sunt : dndu-se o main Turing, M, se oprete M pentru irul vid ? dndu-se o maina Turing , M, exist un ir pentru care M se oprete ? dndu-se o main Turing, M, se oprete M pentru orice ir de intrare ? dndu-se dou maini Turing, M1 i M2 se opresc ele pentru acelai ir de intrare ? dndu-se o main Turing, M este limbajul acceptat de M regulat, independent de context, Turing decidabil ? dndu-se dou gramatici G1 i G2 arbitrare L(G1) = L(G2) ? dndu-se o gramatic G arbitrar este L(G) = ? dndu-se o gramatic G independent de context este G ambigu ?

1.3.3.6. Maina Turing cu limit de timp


Chiar dac o problem poate s fie rezolvat cu ajutorul unei maini Turing dac timpul de rezolvare este mult prea mare nseamn c practic problema nu poate s fie rezolvabil cu ajutorul unei maini Turing. Unul dintre exemplele clasice pentru o astfel de enun este problema comisvoiajorului. Ideea este c un comis-voiajor trebuie s viziteze 10 orae. Se cunosc distanele dintre orae i se cere s se construiasc un intinerariu de lungime minim care s permit comis84

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

85

voiajorului s viziteze toate oraele. Evident, problema este rezolvabil. Numrul de drumuri posibile este finit (9!) i deci o parcurgere a tuturor va produce o soluie. S considerm c 9! este nc o valoare siportabil, dar dac am vorbi de 30 de orae. n acest caz numrul de posibiliti este mai mare dect 1030. Timpul pentru a a analiza toate aceste soluii reprezint mai multe miliarde de viei omeneti. Rezult deci, c din punct de vedere practic definiia de problem rezolvabil/nerezolvabil trebuie s fie redefinit. n continuare vom lucra cu maini Turing cu mai multe benzi. Se poate demonstra c timpul de decizie pentru un limbaj nu depinde de numrul de benzi utilizate. * Fie t o funcie pe numere naturale. Fie L T0 un limbaj i M = (Q, T, m, s) o main Turing cu k piste avnd T0 T. Vom spune c M decide L n timp t dac pentru orice w L
(s, #w#, #, ..., #) |-x (h, #D#, #, ..., #) pentru x t(|w|);

iar pentru w L
(s, #w#, #, ..., #) |-x (h, #N#, #, ..., #) pentru x t(|w|).

Vom spune c L este decidabil n timp t dac exist un k > 0 i o main Turing cu k piste astfel nct s decid L n timp t. Clasa limbajelor decidabile n timp t este reprezentat de TIME(t). Rezult c numrul de pai executai de o main Turing pentru un ir dat depinde de lungimea sa. Deoarece maina Turing trebuie cel puin s tearg irul de intrare, i s scrie un simbol (D sau N) i s i poziioneze capul dup acest simbol nseamn c sunt necesare cel puin |w| + 1 operaii de scriere i |w| + 3 operaii de deplasare. Rezult c pentru funcia t utilizat ca limit de timp t(n) > 2n + 4. S considerm de exemplu maina care decide limbajul:
L = {w {a,b}* | w nu contine sirul aa} #\ ----+b \ / |--/ \b/ / # >L --#L ----->#L/ a a # # RDR RNR

n timp ce maina parcurge irul de intrare de la stnga la dreapta l i terge. M va executa numrul minim de pai, adic M decide L n timp t, cu t(n) = 2n + 4 adic L TIME(t). Acelai lucru se poate scrie sub forma - L TIME(2n + 4). Obiectivul unui studiu de complexitate pentru rezolvarea unei probleme const n construirea unei maini Turing care s asigure c decizia limbajului respectiv se va face n maximum t pai, cu t propus sau dac asta nu este posibil s se construiasc o demonstraie riguroas c o astfel de main nu se poate construi. Se poate demonstra c dndu-se un limbaj L TIME(t) atunci L TIME(t') unde t'(n) = 2n + 18 + _ x t(n) _ unde x este o valoare real orct de mic (_ r _ reprezint cel mai mic numr ntreg m astfel nct m r). Ceea ce exprim rezultatul anterior este faptul c ceea ce conteaz este viteza de cretere i nu factorii constani sau termenii de ordin mai mic. Fie f i g dou funcii pe numere naturale. Vom nota cu f = O(g) dac i numai dac exist o constant c > 0 i un numr ntreg n0 astfel nct: f(n) c g(n) pentru n n0.

85

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

86

d j Dac f(n) = ajn atunci f = O(nd). Adic viteza de cretere polinomial este reprezentat de j=0 rangul polinomului. n afar de polinoame mai exist i alte funcii care dei nu sunt polinomiale sunt mrginite de polinoame. De exemplu n |_log2(n+1)_ = O(n2). Evident creterile polinomiale sunt de preferat celor exponeniale (de forma rn) pentru c se poate demonstra c orice funcie exponenial crete strict mai repede dect una polinomial. Clasa P ( limbajelor decidabile n timp polinomial) este definit ca: P = {TIME(n ) | d > 0} Adic este clasa tuturor limbajelor care pot s fie decise de o main Turing ntr-un timp care este mrginit de o funcie polinomial. * Fie t o funcie pe numere naturale. Fie L T0 i fie M = (Q, T, m, s) o main Turing nedeterminist. Spunem c M accept limbajul L n timp t nedeterminist dac pentru w T0*,
w L daca si numai daca (s, #w#) |-x (h, vau)
d

pentru v, u T , a T i x t(|w|). Vom spune c limbajul L este acceptabil ntr-un timp t nedeterminist dac exist o main M care accept L n timp t nedeterminist. Clasa limbajelor acceptabile n timp t nedeterminist este notat cu NTIME(t). Vom definii NP = {NTIME(nd) | d > 0} Mai puin formal, P este clasa tuturor mulimilor pentru care apartenena unui element poate s fie testat eficient. Acelai lucru nu este adevrat pentru NP. Clasa NP conine probleme pentru care apartenena la P nu a fost demonstrat. Fie L1 T1* i L2 T2*. O funcie g : T1* T2* este calculabil n timp polinomial dac exist o main Turing M care calculeaz f n timp t polinomial. O funcie g : T1* T2* calculabil n timp polinomial. este o transformare polinomial din L1 n L2 dac i numai dac pentru orice w T1*, w L1 dac i numai dac g(w) L2. Cu alte cuvinte irurile din L1 pot s fie transformate n iruri din L2 ntr-un timp polinomial. Se spune c un limbaj L este NP-complet dac i numai dac (a) L NP; (b) pentru L' NP, exist o transformare n timp polinomial din L' n L. Se poate demonstra c dac L este NP-complet atunci P = NP dac i numai dac L P. Deocamdat nu s-a demonstrat c P NP sau P = NP. Exist numeroase probleme "clasice" care sunt NP-complete. Pentru aceste probleme de fapt nu se tie dac exist algoritmi de rezolvare n timp polinomiali. Se consider c este mai probabil c P NP i deci c astfel de algoritmi nu exist. De obicei dac pentru o problem "nou" se dorete s se cerceteze apartenena la clasa P sau NP se ncearc construirea unei transformri polinomiale la una dintre problemele cunoscute (de exemplu problema comis voiajorului este o problem NP-complet). 86

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

87

2. Analiza lexical
Rolul analizei lexicale este de a traduce textul programului ntr-o secven de atomi lexicali. n acest mod se obine un "text" mai uor de prelucrat de ctre celelalte componente ale compilatorului, deoarece se realizeaz o abstractizare a unei infiniti de iruri de intrare n atomi de tip - identificatori, constante, etc. De asemenea prin eliminarea blancurilor i a altor separatori irelevani (ca de exemplu comentarii), textul prelucrat se poate reduce drastic. De cele mai multe ori analiza lexical realizeaz i alte activitati auxiliare ca de exemplu pstrarea evidenei numrului de linii citite. O astfel de informaie este foarte util pentru construirea mesajelor de eroare. Cnd se proiecteaz un analizor lexical se pune n general problema care este nivelul de complexitate al atomilor lexicali considerai. De exemplu n cazul n care un limbaj utilizeaz numere complexe, se pune problema dac analizorul lexical va fi cel care va recunoate o constant de forma:
(<real>, <real>)

producnd un atom lexical corespunztor sau recunoaterea unei astfel de constante ramne n sarcina nivelului analizei sintactice. n general un analizor lexical este specificat sub forma :
p1 {actiune 1} p2 {actiune 2} ... pn {actiune n}

unde pi este o expresie regulata, iar actiune i este o secven de operaii care se execut pentru fiecare subir care corespunde modelului oferit de pi. S considerm de exemplu irurile de caractere 99.E10 i 99.EQ.10, care pot s apara ntr-un program FORTRAN. n primul caz este vorba de numrul 99 x 1010, n al doilea caz de o expresie relaional. Dac analiza se oprete dupa identificarea punctului zecimal cu concluzia c s-a identificat un numr real se observa c n primul caz oprirea se face prea devreme iar n al doilea caz prea trziu. O soluie const din identificarea acestor situaii realizndu-se aa numita cutare nainte. Astfel, pentru cazul considerat, dup recunoaterea irului 99. se mai cerceteaz cel puin un caracter pentru a se hotar dac analiza trebuie s se incheie la 99 sau trebuie s continue pn la 99.E10 . O abordare mai bun consta din cutarea sistematic a celui mai lung subir care satisface unul din modelele p1,...,pn. Dac exist mai multe modele de aceai lungime care sunt satisfcute se va alege o convenie de alegere : de exemplu n ordinea p1,...,pn. Un analizor lexical este de fapt implementarea unui automat finit. Ceea ce se schimb de la un analizor lexical la altul este numai specificarea modelelor cutate i a aciunilor asociate.

87

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

88

inceput subsir -------------------------------| buffer de intrare -------------------------------\ cap de citire \ +-----------+ | simulator |--------------+ | automat | | +-----------+ | | | +-----------+ +-----------+ | tabela | | tabela | | de | | proceduri | | tranzitii | | tratare | +-----------+ | actiuni | +-----------+

S discutm nti cum se construiete un automat finit nedeterminist pornind de la specificaiile analizorului lexical. Se observ c trebuie s se construiasca un AFN care s recunoasca o expresie regulata de forma p1 | p2 | ... | pn. n general automatul care rezult este :
------------------------| +---+ +-----+ | | | | N(p1) |+---+| | ---------> | |-- -->|| || | / | | | |+---+| | / | +---+ +-----+ | +---+ / | | | |/ ------------------------| |\ ------------------------->| s0| \ | | | |\ \ | +---+ +-----+ | | |\\ | | | N(p2) |+---+| | +---+ \ ---------->| |-- -->|| || | \ | | | |+---+| | | | +---+ +-----+ | | | | | ------------------------| ... | | ------------------------| | +---+ +-----+ | | | | | N(pn) |+---+| | +--------->| |-- -->|| || | | | | |+---+| | | +---+ +-----+ | | | -------------------------

Pentru a simula acest automat se utilizeaz o modificare a algoritmului de simulare a AFN pentru a asigura recunoaterea celui mai lung prefix care se potrivete unui model. n acest scop se realizeaz simularea continua pn cnd se obine o mulime de stari pentru care nu mai exist nici o tranziie posibil pentru simbolul curent. Se presupune c limbajul este astfel nct bufferul de intrare nu poate fi mai scurt dect o lexema (irul de caractere corespunztor

88

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

89

unui atom lexical recunoscut). De exemplu orice compilator are o limit (eventual foarte mare) pentru numrul de caractere dintr-un identificator. Ori de cte ori ntr-o mulime de stri se adaug o stare final se va memora att poziia n irul de intrare ct i modelul pi corespunztor. Dac n mulimea respectiv exist deja o stare final atunci se va memora numai unul dintre modele (conform conveniei stabilite). Cnd se ajunge n situaia de terminare se revine la ultima poziie n irul de intrare la care s-a facut o recunoatere a unui model. S considerm de exemplu un analizor lexical specificat n modul urmtor :
a abb a*b+

Pentru acest analizor nu s-au specificat aciunile corespunztoare unitilor lexicale. Automatul finit nedeterminist corespunztor este:
+---+ +-----+ | | a |+---+| ---------> | 1 |----->|| 2 || / | | |+---+| / +---+ +-----+ +---+ / +---+ +---+ +---+ +-----+ | |/ | | a | | b | | b |+---+| | 0 |-------------> |3 |------>| 4 |----->| 5 |----->|| 6 || | |\ | | | | | | |+---+| +---+ \ +---+ +---+ +---+ +-----+ \ +---+ +-----+ \ | | b |+---+| --------->| 7 |----->|| 8 || | | |+---+| +---+ +-----+ /\ / \ -----a b

S considerm comportarea acestui automat pentru irul de intrare aaba :


a a b a {0,1,3,7} - {2,4,7} - {7} - {8} -

Se observ c prima stare de acceptare este 2 n care se ajunge dup primul simbol a, apoi va fi gsit starea 8 la care se revine dup ce se ajunge la terminare dupa simbolul a de la sfritul irului. S considerm i varianta care utilizeaz un automat determinist. Pentru exemplul anterior se obine automatul determinist echivalent descris de urmtoarea tabela de tranziii:
| intrare | model recunoscut | a b | ---------------+----------------+--------------------{0,1,3,7} | {2,4,7} {8} | ---------------+----------------+--------------------{2,4,7} | {7} {5,8} | a (pentru 2) ---------------+----------------+--------------------{8} | {8} | a*b+ stare

89

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

90

---------------+----------------+--------------------{7} | {7} {8} | ---------------+----------------+--------------------{5,8} | {6,8} | a*b+ ---------------+----------------+--------------------{6,8} | {8} | abb ------------------------------------------------------

Se observ c starea {6,8} conine dou stri finale deci recunoate att modelul a*b+ ct i abb. Considerm prin convenie c model recunoscut n acest caz trebuie s fie abb. De exemplu pentru irul abba evoluia va fi :
a b b a {0,1,3,7} - {2,4,7} - {5,8} - {6,8} -

2.1. Interfaa analizorului lexical


Dupa cum se tie analizorul lexical funcionez ca un modul n cadrul unui compilator sau a oricrui program care realizeaz prelucrri ce necesit identificarea unor iruri ce pot fi descrise de o gramatic regulat. n funcionarea sa analizorul lexical interacioneaz cu celelalte componente ale compilatorului prin intermediul unei interfee specifice :
+---------------+ insert_s +-------------------+ | | +---------> | | | Program sursa | | | tabela de simboli | | | | +------| | +---------------+ | | +-------------------+ | /|\ | | | |revenire | \|/ lookup_s | | +------------------+ | +-------| | | | Analizor lexical |<------+ +----------->| | | lookup_c avans_intrare() +------------------+ | anlex | | | insert_c | +--------------------+ | | | +---------------------+ | | ||| | | | Analizor sintactic |<--+ | +--->| tabela de constante | | | | | | +--------------------+ | +---------------------+ \|/ eroare +---------------+ | | | Tratare erori | | | +---------------+

Interaciunea cu fiierul surs se face prin intermediul a dou subprograme : avans_intrare (care preia caracterul urmtor din programul sursa) i revenire (care realizeza revenirea napoi n textul surs, dac ntotdeauna revenirea se face cu un singur caracter se poate utiliza o funcie de tip ungetc). Tabela de simboli este o structur de date al carui rol este de a memora informaii referitoare la atomii lexicali de tip identificator recunoscui de ctre analizorul lexical. Informaiile referitoare la acesti simboli sunt utilizate att n cadrul analizei sintactice ct i n faza de generare de cod. Introducerea simbolilor n tabela de simboli se face de ctre analizorul lexical, completarea informaiilor realizndu-se de ctre analizorul sintactic care va aduga

90

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

91

informaii ca de exemplu tipul simbolului (procedura, variabila, eticheta, etc) i modul de utilizare. Legatura cu tabela de simboli se face prin intermediul a doua proceduri : insert_s i lookup_s. Procedura insert_s are ca argumente un ir de caractere i codul atomului lexical reprezentat de ir. Rezultatul procedurii este adresa n tabela de simboli la care s-a facut memorarea simbolului. Procedura lookup_s are ca argument un ir iar ca rezultat adresa n tabela de simboli la care se gsete simbolul reprezentat de irul respectiv. Dac n tabela nu exist irul cutat rezultatul este 0. Pentru cuvintele cheie de obicei se face o tratare speciala, de exemplu se poate initializa tabela de simboli cu intrari corespunztoare tuturor cuvintelor cheie din limbajul respectiv executnd apeluri de forma :
insert_s("if", cod_if); insert_s("else", cod_else);

etc. nainte de a se ncepe execuia efectiv a compilatorului. n acest caz recunoaterea cuvintelor cheie se va face apoi ntr-un mod similar cu a oricarui alt identificator. Se observ deci de ce n majoritatea limbajelor de programare cuvintele cheie nu pot s fie utilizate ca nume cu alt semnificaie. O astfel de tratare are avantajul ca n cazul n care se face o declaraie de tip de forma:
typedef int intreg;

dup introducerea n tabela de simboli a cuvintului intreg de ctre analizorul lexical, analizorul sintactic va putea s completeze apoi intrarea n tabela de simboli cu informaiile corespunztoare numelui unui tip. n acest mod n urmtoarele ntlniri ale acestui cuvnt analizorul lexical va putea s transmit ca ieire atomul lexical corespunztor unui nume de tip. n cazul constantelor analizorul lexical realizeaz recunoaterea acestora i memoreaz valorile corespunztoare n tabela de constante pentru a permite utilizarea ulterioar n cadrul generrii de cod. Analizorul sintactic apeleaz de obicei analizorul lexical ca pe o funcie care are ca valoare codul atomului lexical recunoscut de ctre analizorul lexical. n general ntre analizorul lexical i analizorul sintactic trebuie s se mai transfere i alte informaii ca de exemplu adresa n tabela de simboli sau n tabela de constante a unui identificator, cuvntul cheie respectiv constanta identificata de ctre analizorul lexical. Aceste informaii reprezint atributele atomului lexical. Un compilator recunoate erori n toate fazele sale: analiza lexical, sintactic i n generarea de cod. Dac se intlnete o eroare, se pune problema localizrii sale ct mai precise i apoi a modului n care se continua analiza astfel nct n continuare s se semnaleze ct mai puine erori care decurg din aceasta. Un aspect important al interfetei analizorului lexical o constituie interfaa cu sistemul de operare corespunztoare citirii textului programului surs. n general este bine ca interfaa cu sistemul de operare s fie ct mai bine separat de restul compilatorului pentru a se obine un cod portabil prin pstrarea aspectelor dependente de main n cadrul funciilor care formeaz aceasta interfa. Din timpul consumat de ctre procesul de compilare o parte foarte important se consum n cadrul analizei lexicale. La rndul sau partea cea mai consumatoare de timp este de obicei partea legat de operaiile de citire. n mod standard obinerea unui caracter n execuia unui program presupune copierea acestuia n mai multe etape - de pe disc n zona tampon a sistemului de operare, din aceast zon n zona prevazut n program, de unde apoi se face copierea n variabila care memoreaz caracterul curent.

91

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

92

Chiar i n cazul unui analizor lexical foarte simplu care ar trebui s recunoasc irurile : xxyy, xx i y dac n irul de intrare se ntlneste irul xxy trebuie s se mai citeasc nc un caracter pentru a se putea stabili dac este vorba de atomul lexical xxyy sau de atomii lexicali xx i y. Se observ ca n acest caz utilizarea unei proceduri de tip ungetc() nu este suficient. n general o colecie de funcii care asigur citirea textului surs pentru analizorul lexical trebuie s satisfac urmtoarele condiii: funciile trebuie s fie ct mai rapide, realiznd un numr minim de copieri pentru caracterele parcurse; existena unui mecanism care s permit examinarea unor caractere n avans i revenirea pe irul de intrare; s admit atomi lexicali suficient de lungi;

Pentru a obine o utilizare eficient a operaiilor legate de accesul la disc este necesar ca dimensiunea bufferuluis fie adaptat modului de alocare a spatiului pe disc. Astfel, pentru sistemul de operare MS-DOS utilizarea unui buffer mai mic dect 512 octei nu are nici o justificare (o operaie de citire va citii cel puin un sector de pe disc). De preferat este ca bufferul s fie un multiplu al unitii de alocare a spatiului pe disc.

2.2. Un exemplu elementar de analizor lexical


S considerm analizorul lexical corespunztor unui translator pentru limbajul descris de urmatoarea gramatic :
lista eof expresie; lista | expresie + termen | expresie - termen | termen termen termen * factor | termen / factor | termen div factor | termen mod factor | factor factor (expresie) | identificator | numr identificator litera rest_id rest_id litera rest_id | cifra rest_id | numr cifra numr | cifra litera A | B | ... z cifra 0|1|2|3|4|5|6|7|8|9 S lista expresie

Se observ ca nivelul analizei lexicale printr-o transformare corespunztoare presupune recunoaterea urmtorilor atomi lexicali :
atom lexical numr identificator div mod ( ) * / actiune calcul valoare introduce n tabela de simboli

92

Irina Athanasiu
+ ; eof

10/4/2003

Limbaje formale si translatoare

93

n afar de recunoaterea acestor atomi analizorul lexical realizeaz i o eliminare a blancurilor i a unor caractere speciale de tip '\n' sau '\t'. Avnd n vedere tipul atomilor lexicali ce trebuie s fie recunoscui nu este necesar utilizarea unei interfee sofisticate cu sistemul de operare. Tabela de simboli trebuie s memoreze pentru fiecare identificator (cuvnt cheie) - irul de caractere respectiv, codul asociat (prin intermediul cruia va fi tratat de ctre analizorul lexical) i eventual alte atribute semnificative pe care le poate aduga analiza sintactic. Deoarece lungimea irurilor care formeaz identificatorii poate s fie foarte diferit pentru a se asigura o bun utilizare a memoriei se va utiliza o tabel de simboli format dintr-un vector n care se nregistreaz irurile corespunztoare cuvintelor cheie i identificatorilor recunoscui n textul surs i o tabel cu dou sau mai multe colane. n tabel, fiecare intrare este asociat unui simbol, i conine adresa n vectorul care memoreaz irurile i codul asociat simbolului respectiv.
sir simboli tabela de simboli lexptr atom_lexical

| | | +-----------------------------------| | DIV | | |----+---------------| | +-------------------| | MOD | | | |----+---------------| | | +---| | IDENTIFICATOR | | | | | | | \|/ \|/ \|/ +---------------------------------------------------+ | d | i | v |EOS| m | o | d |EOS| a | l | f | a |EOS| +---------------------------------------------------+

Analizorul lexical poate s fie descris de urmtorul graf :

93

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

94

blanc,\n,\t /A7 cifra, -litera / A3 \/ -+-------+ \/ +-----+ | | litera / A2 +---+ litera / A4 |+---+| | |------------>| 1 | --------------> || || | | +---+ cifra |+---+| | | cifra / A3 +-----+ | | -| | \/ +-----+ | | cifra / A2 +---+ cifra / A5 |+---+| | 0 |------------->| 2 |-------------- > || || | | +---+ |+---+| | | +-----+ | | +-----+ | | */A1,//A1,+/A1,-/A1,(/A1,)/A1,;/A1 |+---+| | |---------------------------------> || || | | EOF/A6 || || | |----------------------------------> |+---+| +-------+ +-----+

n graf au fost evideniate caracterele i aciunile corespunztoare acestora. Interfaa cu analizorul sintactic se realizeaz prin intermediul rezultatului apelului analizorului lexical (valoarea funciei anlex()) i prin variabila tokenval. Valoarea ntoars de funcia anlex() este codul atomului lexical recunoscut. Variabila tokenval primete o valoare care depinde de tipul atomului lexical recunoscut. Astfel pentru un numr aceast variabil va conine valoarea numrului iar pentru un identificator adresa n tabela de simboli (la care a fost introdus sau regsit identificatorul respectiv). Atomii lexicali care presupun asignarea unor coduri distincte sunt : NUMR(256), DIV(257), MOD(258), IDENTIFICATOR(259), GATA(260). Pentru ceilali atomi lexicali codul, corespunde codului ASCII al caracterului ce reprezint atomul lexical respectiv. Fiecare identificator este asamblat ntr-o zon tampon auxiliar buffer_intrare. n momentul n care se ncheie construirea unui identificator (se identific sfritul irului) se poate face cutarea acestuia n tabela de simboli, eventual se va introduce simbolul respectiv n tabela de simboli. n legatura cu tabela de simboli programul conine trei proceduri : init() realizeaz introducerea n tabela de simboli a uvintelor cheie lookup(s) - caut n tabela de simboli irul de caractere transmis ca argument. Rezultatul intors de aceast procedur este adresa relativ n tabela de simboli. insert(s,t) - introduce un simbol nou la sfritul tabelei de simboli. Al doilea argument de apel este codul atomului lexical reprezentat de irul respectiv. trebuie s fie executate n legatur cu execuia analizorului lexical sunt

Aciunile ce urmtoarele:

A1 : tokenval = NIMIC; return caracter; A2 : b = 0 ;

94

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

95

A3 : buffer_intrare[b++] = caracter; caracter = getchar(); if (b >= BSIZE) eroare("sir prea lung"); A4 : buffer_intrare[b] = EOS; if (caracter != EOF) ungetc(caracter, stdin); p = lookup(buffer_intrare); if (p == 0) p = insert(buffer_intrare, IDENTIFICATOR); tokenval = p; return tabela_simboli [p].atom_lexical; A5 : buffer_intrare[b] = EOS; if (caracter != EOF) ungetc(caracter, stdin); tokenval = atoi(buffer_intrare); return NUMR; A6 : tokenval = NIMIC; return GATA; A7 : if (caracter == ' '|| caracter == '\t') ; else if (caracter == '\n') lineno++;

Corespunztor va rezulta urmtorul program care citete i afieaz codurile atomilor lexicali intilnii.
#include #include #include #include "stdlib.h" "stdio.h" "ctype.h" "string.h"

#define BSIZE 128 #define NIMIC -1 #define EOS '\0' #define #define #define #define #define NUMAR 256 DIV 257 MOD 258 IDENTIFICATOR 259 GATA 260

#define MAXSIR 999 #define MAXSIM 100 /* variabile globale */ static static static static static static int int int int char int ultimul_caracter = -1; ultima_intrare = 0; tokenval = NIMIC; lineno = 1; buffer_intrare[BSIZE]; caracter, p, b; /* ultimul caracter citit */ /* cod atom lexical */ /* numar linie cod */

95

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

96

/* tabela de simboli */ static char sir_simboli [MAXSIR]; /* sir de nume identificatori */ struct intrare { char *lexptr; int atom_lexical; }; static struct intrare tabela_simboli [MAXSIM]; static struct intrare cuvinte_cheie[] = { "div", DIV, "mod", MOD, 0, 0 }; /* prototipuri functii */ static static static static static static int int void void void int lookup(char s[]); insert(char s[],int tok); init(void); a3(void); eroare (char *m); lexan(void);

/* cauta n tabela de simboli */ static int lookup(char s[]) { int p; for (p = ultima_intrare; p > 0; p--) if (strcmp(tabela_simboli[p].lexptr, s) == 0) return p; return 0; } /* introducere n tabela de simboli */ static int insert(char s[], int tok) { int len; len = strlen(s); if (ultima_intrare + 1 >= MAXSIM) eroare("s-a depasit dimensiunea tabelei de simboli"); if (ultimul_caracter + len + 1 >= MAXSIR) eroare("s-a depasit dimensiunea tabelei de simboli"); tabela_simboli[++ultima_intrare].atom_lexical = tok; tabela_simboli[ultima_intrare].lexptr = &sir_simboli[ultimul_caracter + 1]; ultimul_caracter = ultimul_caracter+len +1; strcpy(tabela_simboli[ultima_intrare].lexptr,s); return ultima_intrare; }

96

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

97

/* initializarea tabelei de simboli */ static void init() { struct intrare *p; for (p = cuvinte_cheie; p -> atom_lexical;p++) insert(p->lexptr, p->atom_lexical); } /* tratarea erorilor */ static void eroare (char *m) { printf("line %d: %s\n", lineno, m); exit(1); } /* analizorul lexical */ static void a3() { buffer_intrare[b++] = caracter; caracter = getchar(); if (b >= BSIZE) eroare("ir prea lung"); } static int lexan() { while(1) { caracter = getchar(); /* A7 */ if (caracter == ' '|| caracter == '\t') ; /* eliminare blancuri else if (caracter == '\n') lineno++; else if (isdigit(caracter)) /* caracter este { /* A2 */ b = 0; while (isdigit(caracter)) /* A3 */ a3(); /* A5 */ buffer_intrare[b] = EOS; if (caracter != EOF) ungetc(caracter, stdin); tokenval = atoi(buffer_intrare); return NUMR; } else if (isalpha(caracter)) /* caracter este { /* A2 */ b = 0; while (isalnum(caracter)) /* litera /* A3 */ a3();

si tab-uri */ cifra */

litera */ sau cifra */

97

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

98

/* A4 */ buffer_intrare[b] = EOS; if (caracter != EOF) ungetc(caracter, stdin); p = lookup(buffer_intrare); if (p == 0) p = insert(buffer_intrare, IDENTIFICATOR); tokenval = p; return tabela_simboli [p].atom_lexical; } else if (caracter == EOF) { /* A6 */ tokenval = NIMIC; return GATA; } else { /* A1 */ tokenval = NIMIC; return caracter; } } } void main() { int simbol_curent; init(); simbol_curent = lexan(); while (simbol_curent != GATA) { printf(" %d\n",simbol_curent); simbol_curent = lexan(); } }

De fapt orice analizor lexical are aceai form general, i construirea unui analizor lexical parcurge ntotdeauna aceleai etape: 1. construirea expresiilor regulate care descriu atomii lexicali care urmeaz s fie recunoscui de ctre analizorul lexical (nu se poate automatiza) 2. construirea automatului finit nedeterminist care accept expresiile regulate (se poate face n mod automat) 3. construirea automatului finit determinist echivalent cu cel nedeterminist construit n pasul anterior (se poate face n mod automat) 4. implementarea unui simulator pentru un automat finit determinist. Acest simulator poate s fie general (adic s poat s fie utilizat pentru orice automat finit determinist), sau poate s fie construit special pentru automatul respectiv. De fapt n pasul trei se construiete tabela de tranziie a automatului. Dac simulatorul este general (adic este capabil s simuleze orice automat specificat prin tabela de tranziii) se observ c ncepnd din pasul al doilea, toate operaiile se pot face n mod automat adic se poate construi un program care pornind de la expresiile regulate i aciunile asociate s genereze un analizor lexical. Cel mai cunoscut program de acest tip este lex. Iniial acest program a fost utilizat numai sub UNIX. n prezent exist variante i pentru MS-DOS. Specificaiile lex pentru analizorul lexical simplu considerat anterior sunt:
%{ #define NOTHING -1 #define NMBER 256

98

Irina Athanasiu
#define #define #define #define DIV 257 MOD 258 IDENTIFIER 259 FINISH 260

10/4/2003

Limbaje formale si translatoare

99

#define MAXSIR 999 #define MAXSYM 100 /* global variables */ int int int int int /* symbol table */ char string_array [MAXSIR]; /* string of names */ struct entry { char *lexptr; int token; }; struct entry symbol_table [MAXSYM]; struct entry reserved_words [] = { "div", DIV, "mod", MOD, 0, 0 }; void error (char *m) { printf("line %d: %s\n", lineno, m); exit(1); } /* lookup in symbol table */ int lookup(char s[]) { int p; for (p = last_entry; p > 0; p--) if (strcmp(symbol_table[p].lexptr, s) == 0) return p; return 0; } /* inserting in symbol table */ int insert(char s[], int tok) { int len; len = strlen(s); if (last_entry + 1 >= MAXSYM) error("too many symbols"); last_character = -1; last_entry = 0; tokenval = NOTHING; lineno = 1; p; /* last character */ /* current token */

99

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

100

if (last_character + len + 1 >= MAXSIR) error("too many or too long strings"); symbol_table[++last_entry].token = tok; symbol_table[last_entry].lexptr = &string_array[last_character + 1]; last_character = last_character+len +1; strcpy(symbol_table[last_entry].lexptr,s); return last_entry; } /* initialization for symbol table */ void init() { struct entry *p; for (p = reserved_words; p-> token;p++) insert(p->lexptr, p->token); } %} /* the scanner */ delim nl ws letter digit letgit [ \t] [\n] {delim}+ [A-Za-z] [0-9] [A-Za-z0-9]

%% div return DIV; mod return MOD; {letter}{letgit}* { p = lookup(yytext); if (p == 0) p = insert(yytext, IDENTIFIER); tokenval = p; return symbol_table [p].token; } {digit}+ } {nl} {delim}+ <<EOF>> . lineno++; return NOTHING; return NOTHING; return FINISH; return yytext[0]; { tokenval = atoi(yytext); return NMBER;

%% void main() { int symbol_current; yyin = stdin; init(); tokenval = NOTHING; symbol_current = yylex();

100

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

101

while (symbol_current != FINISH) { if (symbol_current != NOTHING) printf(" symbol = %i, tokenval = %i\n", symbol_current, tokenval); tokenval = NOTHING; symbol_current = yylex(); } }

3. Analiza sintactic
Rolul fazei de analiza sintactica este de a construi arborii de derivare corespunztori propoziiilor din limbajul respectiv verificnd buna structurare a acestora. Termenul utilizat n literatura de specialitate pentru aceasta aciune este "parsing". Considernd gramatica expresiilor aritmetice :
(1) (2) (3) (4) (5) (6) T T F F +T T T*F F () a

i irul de intrare a * (a + a) s construim o derivare stnga :


2 3 4 6 5 1 T T * F F * F a * F a * () 2 4 6 a * ( + T) a * (T + T) a * (F + T) 4 6 a * (a + T) a * (a + F) a * (a + a)

Lista produciilor aplicate este 23465124646. Pentru derivarea dreapta se obine: 2 3 5 1 4 T T * F T * () T * ( + T) 6 2 4 T * ( + F) T * ( + a) T * (T + a) 6 4 6 T * (F + a) T * (a + a) F * (a + a) a * (a + a) n acest caz lista produciilor care trebuie s fie aplicate pentru sintetizarea neterminalului de start al gramaticii este 64642641532. Ambele liste de producii descriu acelai arbore de derivare.
|2 T /|\3 T * F 4 | /|\ 5

101

Irina Athanasiu

10/4/2003
F ( 6 | /| a + |2 T |4 F |6 a ) \1 T |4 F |6 a

Limbaje formale si translatoare

102

Se observ c pentru derivarea stnga este vorba de o parcurgere RSD, iar pentru derivarea drapta parcurgerea arborelui este SDR. Evident dndu-se o parcurgere i produciile gramaticii se poate reconstrui arborele de derivare. n general pentru o gramatic independent de context se poate construi un automat de tip push down care s produc pentru un ir de intrare dat lista de producii care duce la acceptarea irului respectiv. n acest scop se defineste notiunea de translator push down. Un astfel de translator se construiete adaugnd o ieire unui automat push down. La fiecare micare a automatului push down, translatorul va emite un ir finit de simboli. Deci definiia este:
PDT = (Q, T, Z, X, m, q0, z0, F)

unde X este un alfabet finit de ieire, iar funcia m este definit ca m : Q x (T {}) x Z P(Q x Z* x X*). n acest caz o configuraie a automatului are patru componente : (q, , , ), q Q, T*, Z*, X*, unde reprezint irul de simboli generat pn la momentul curent de ctre automat. Se spune c automatul realizeaz traducerea irului T* n irul X* dac este indeplinit condiia :
(q0, , z0, ) |-* (q, , w, ) q F, w Z*

n general traducerile realizate de ctre translator sunt :


{ (, ) | (q0, , z0, ) |-*(q, , , ) q F, Z*, T*, X*}

Similar definitiilor referitoare la automatele push down exist noiunile de translatare prin stiv goal i translator push down extins. Pentru o gramatic independent de context putem s construim un translator push down care produce lista produciiilor corespunztoare derivrilor stnga i dreapta. S considerm din nou gramatica expresilor aritmetice. Rezult translatorul care produce lista produciilor corespunztoare derivrilor stnga :
({q},{a,+,*,(,)},{, T, F,a,+,*,(,)}, {1, 2, ..., 6}, m, q, , )

cu
m(q, m(q, m(q, m(q, , , , x, ) T) F) x) = = = = {(q, {(q, {(q, {(q, + T, 1), (q, T, 2)} T * F, 3), (q, F, 4)} (), 5), (q,a,6)} , )} x T

De exemplu pentru irul a * (a + a) se obine evoluia :

102

Irina Athanasiu

10/4/2003
(a (a (a (a (a (a (a ,

Limbaje formale si translatoare

103

(q, a * (a + a), , ) |- (q, a * |- (q, a * |- (q, a * |- (q, a * |- (q, * |- (q, |- (q, |-+ (q, ,

+ a), T, 2) + a), T * F, 23) + a), F * F, 234) + a), a * F, 2346) + a), * F, 2346) + a), F, 2346) + a), (), 23465) 23465124646)

n cazul derivrii dreapta se obine translatorul push down:


({q}, {a,+,*,(,)}, {,T,F,a,+,*,(,),$}, {1,2,...,6}, m, q, $, )

cu
m(q, m(q, m(q, m(q, m(q, m(q, m(q, m(q, , , , , , , x, , + T) T) T * F) F) ()) a) ) $)} = {(q, , = {(q, , = {(q, T, = {(q, T, = {(q, F, = {(q, F, = {(q, x, = {(q, , 1)} 2)} 3)} 4)} 5)} 6)} )} )}

xT

Pentru acelai ir se obine secvena de micri:


(q, a * (a + a), $, ) |||||||||||||||||||(q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, * (a + a), $a, ) * (a + a), $F, 6) * (a + a), $T, 64) (a + a), $T *, 64) a + a), $T * (, 64) + a), $T * (a, 64) + a), $T * (F, 646) + a), $T * (T, 6464) + a), $T * (, 64642) a), $T * ( +, 64642) ), $T * ( + a, 64642) ), $T * ( + F, 646426) ), $T * ( + T, 6464264) ), $T * (, 64642641) , $T * (), 64642641) , $T * F, 646426415) , $T, 6464264153) , $, 64642641532) , , 64642641532)

Se observ c cele dou translatoare construite sunt nedeterministe. Se pune problema dac ntotdeauna un astfel de translator poate s fie simulat determinist deoarece ceea ce ne intereseaz este s obinem analizoare sintactice respectiv compilatoare ct mai eficiente i cu o comportare determinist.

103

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

104

Exist gramatici pentru care aceasta condiie nu poate s fie ndeplinit. De exemplu, pentru o gramatic recursiv stnga nu se poate construi un translator care s produc irul produciilor dintr-o derivare stnga i s poata s fie simulat determinist. Pentru fiecare tip de analizor sintactic(ascendent sau descendent) exist cte o clasa de gramatici pentru care se poate construi un translator determinist dac translatorul are acces la urmtorii k simboli de pe irul de intrare. Cele doua clase se numesc LL(k) respectiv LR(k). n denumire prima liter (L) reprezint tipul de parcurgere al irului - de la stnga (Left) la dreapta. A doua litera (L sau R) specific tipul derivarii - stnga (Left) sau dreapta (Right). Micrile translatorului se fac innd seama de starea curent (starea unitii de control i coninut stiv) i de urmtorii k simboli de pe irul de intrare. S considerm de exemplu urmtoarea gramatic:
(1) (2) (3) (4) (5) (6) S S A A B C BAb CAc BA a a a

Se observ c L(G) = aa+b + aa+c. Gramatica nu este nici LR(k) i nici LL(k) deoarece nu se tie dac primul a dintr-un ir din L(G) este generat utiliznd produciile 1 i 5 sau 2 i 6. Aceasta informaie este aflat abia cnd se ajunge la sfritul irului i se citete ultimul simbol. Se observ c de fapt problema este c nu se tie cte caractere trebuie s fie cercetate n avans pentru a lua o decizie corect. Se poate arta c dac o gramatic este LL(k) ea este i LR(k) dar exist gramatici LR(k) care nu sunt LL(k). Cu alte cuvinte gramaticile LL(k) sunt un subset al gramaticilor LR(k).

104

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

105

3.1. Analiza sintactica top - down


Analiza sintactic top-down poate s fie interpretat ca operaia de construire a arborilor de derivare pornind de la rdcin i adaugnd subarbori de derivare ntr-o ordine prestabilit. S considerm de exemplu gramatica S cAd, A ab | a i irul de intrare cad. Construirea arborelui de derivare pentru acest ir pornete de la simbolul de start al gramaticii S cu capul de citire pe irul de intrare poziionat pe caracterul c. Pentru S se utilizeaz producia S cAd i se obine arborele de derivare :
S /|\ /|\ c A d

n acest moment se observ c frunza cea mai din stnga corespunde cu primul caracter din irul de intrare. n acest caz se avanseaz cu o poziie pe irul de intrare i n arborele de derivare. Frunza curent din arborele de derivare este acum A i se poate aplica una dintre produciile corespunztoare acestui neterminal :
S /|\ /|\ c A d /\ / \ a b

Se poate avansa pe irul de intrare i n arbore deoarece avem din nou coincidena simboliilor terminali. n acest moment se ajunge la compararea simbolului d din irul de intrare cu simbolul b din arbore, corespunztor trebuie s se revin cautndu-se o nou variant pentru A. Rezult c capul de citire trebuie s fie readus n poziia simbolului a. Dac acum se utilizeaz producia A a se obine arborele :
S /|\ /|\ c A d | | a

n continuare se va ajunge la acceptarea irului de intrare. Din cele prezentate anterior rezult dou observaii : n general implementarea presupune utilizarea unor tehnici cu revenire (backtracking); dac gramatica este recursiv stnga algoritmul poate conduce la apariia unui ciclu infinit.

105

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

106

3.1.1. Analiza sintactica predictiva (descendent recursiva)


Dezavantajul abordrii anterioare const n necesitatea revenirilor pe irul de intrare ceea ce conduce la complicarea deosebit a algoritmilor i mai ales a structurilor de date implicate deoarece automatul cu stiv corespunztor cazului general trebuie s fie nedeterminist. Exist ns gramatici pentru care dac se utilizeaza transformri, prin eliminarea recursivitatii stnga i prin factorizare se obin gramatici care pot s fie utilizate pentru analiza top-down fr reveniri. n acest caz dndu-se un simbol de intrare curent i un neterminal exist o singur alternativ de producie prin care din neterminalul respectiv s se deriveze un ir care ncepe cu simbolul de intrare care urmeaz. Pentru proiectarea analizoarelor predictive se utilizeaz diagrame de tranziie. O diagram de tranziie este un graf care prezint produciile corespunztoare unui neterminal. Etichetele arcelor reprezint atomi lexicali sau simboli neterminali. Fiecare arc etichetat cu un atom lexical indic tranziia care urmeaz s se execute dac se recunoate la intrare atomul lexical respectiv. Pentru arcele corespunztoare neterminalelor se vor activa procedurile corespunztoare neterminalelor respective. Pentru a construi o diagrama de tranziie pentru un neterminal A ntr-o gramatica n care nu exist recursivitate stnga i n care s-a fcut factorizare stnga se procedeaz n modul urmtor : 1. se creaz dou stri: iniial i final; 2. pentru fiecare producie A X1 X2 ... Xn se va crea o cale format din arce ntre starea iniial i starea final cu etichetele X1 X2 ... Xn. Analizorul predictiv care lucreaz asupra diagramei de tranziii funcioneaz n modul urmtor. Starea iniial din care se ncepe analiza este starea corespunztoare simbolului de start al gramaticii. Dac la un moment dat analizorul se gsete ntr-o stare s din care exist un arc etichetat cu a spre o stare t i simbolul curent de pe irul de intrare este a T atunci analizorul se va deplasa pe irul de intrare cu o poziie la dreapta i va trece n starea t. Dac din starea s exist un arc etichetat cu un neterminal A spre starea t atunci analizorul trece n starea iniial corespunztoare neterminalului A fr s avanseze pe irul de intrare. Dac se reuete s se ajung la starea final pentru A se va trece n starea t ( se observ c n acest caz se consider c s-a "citit" A din irul de intrare). Dac din starea s exist o -tranziie spre starea t atunci analizorul poate trece direct n stare t fr s se faca nici o deplasare pe irul de intrare. Ideea analizei sintactice predictive const din identificarea a simbolului curent de pe banda de intrare cu nceputul unei producii pentru simbolul neterminal curent. Acest tip de abordare funcionez dac diagrama care reprezint produciile gramaticii este determinist. S considerm de exemplu gramatica pentru expresii aritmetice fr recursivitate stnga : TE', ' +TE' | , T FT', T' *FT' | , F () | a. Diagramele de tranziie corespunztoare sunt :
: +---+ +---+ +-----+ | | T | | ' |+---+| | 0 |-----| 1 |----|| 2 || | | | | |+---+| +---+ +---+ +-----+

106

Irina Athanasiu ':

10/4/2003

Limbaje formale si translatoare

107

+---+ +---+ +---+ +-----+ | | + | | T | | '|+---+| | 3 |-----| 4 |----| 5 |---|| 6 || | | | | | | |+---+| +---+ +---+ +---+ +-----+ | +---------------------------+ T: +---+ +---+ +-----+ | | F | | T' |+---+| | 7 |-----| 8 |----|| 9 || | | | | |+---+| +---+ +---+ +-----+ T': +----+ +----+ +----+ +------+ | | * | |F | | T'|+----+| | 10 |-----| 11 |----| 12 |---|| 13 || | | | | | | |+----+| +----+ +----+ +----+ +------+ | +-------------------------------+ F: +----+ +----+ +----+ +------+ | | ( | | | | ) |+----+| | 14 |-----| 15 |----| 16 |---|| 17 || | | | | | | |+----+| +----+ +----+ +----+ +------+ | a +-------------------------------+

Acest grup de diagrame de tranziie prezint aparent dezavantajul existenei - tranziiilor care pare s confere un caracter nedeterminist analizorului sintactic predictiv corespunztor acestor diagrame, dar acest aspect poate s fie rezolvat simplu. De exemplu pentru ' se va alege n implementare o -tranziie dac i numai dac simbolul care urmeaz la intrare nu este +, etc. Diagramele de tranziie obinute direct din gramatica pot s fie n continuare simplificate prin cteva transformri simple. De exemplu observnd ca n diagrama de tranziie pentru ' apare un arc etichetat cu ' se pot face urmtoarele transformri :
': +------------------------+ | | V | +---+ +---+ +---+ | | | + | |T | || | 3 |-----| 4 |----| 5 |---+ | | | | | | +---+ +---+ +---+ +-----+ | |+---+| +--------------------- || 6 || |+---+| +-----+

i apoi

107

Irina Athanasiu
':

10/4/2003

Limbaje formale si translatoare

108

+---------------+ | | V | +---+ +---+ | | | + | |T| | 3 |-----| 4 |---+ | | | | +---+ +---+ +-----+ | |+---+| +--------------------- || 6 || |+---+| +-----+

Din
: +---+ +---+ +-----+ | | T | | ' |+---+| | 0 |-----| 1 |----|| 2 || | | | | |+---+| +---+ +---+ +-----+

se obine :
: T +---------------+ | | V | +---+ +---+ +---+ | | | T | | + | | | | 0 |-----| 3 |-----| 4 |---+ | | | | | | +---+ +---+ +---+ +-----+ | |+---+| +--------------------- || 6 || |+---+| +-----+

i apoi pentru c strile 0 i 4 sunt echivalente se obine :


: + +---------------+ T+|T | | V | +---+ +---+ | | | T | | | | 0 |-----| 3 |---+ | | | | +---+ +---+ +-----+ | |+---+| +----------- || 6 || |+---+| +-----+ * +---------------+ | | V | TF*T|F

T:

108

Irina Athanasiu

10/4/2003
+---+ +---+ | | | F | | | | 7 |-----| 8 |---+ | | | | +---+ +---+ +------+ | |+----+| +----------- || 13 || |+----+| +------+

Limbaje formale si translatoare

109

F: F () | a +----+ +----+ +----+ +------+ | | ( | | | | ) |+----+| | 14 |-----| 15 |----| 16 |---|| 17 || | | | | | | |+----+| +----+ +----+ +----+ +------+ | a +-------------------------------+

Analizorul sintactic corespunztor acestor diagrame de tranziie este :


#include "stdio.h" #include "ctype.h" int caracter_curent; /* prototipuri functii */ static static static static void void void void gasit(int t); expr(void); termen(void); factor(void);

static void gasit(int t) { if (caracter_curent == t) { putchar(caracter_curent); caracter_curent = getchar(); } else { printf("\neroare \n"); exit(1); } }

/* TE', ' +TE' | , + T | T */ static void expr() { termen(); while (1)

109

Irina Athanasiu
if (caracter_curent == '+') { gasit('+'); termen(); } else break; } /*

10/4/2003

Limbaje formale si translatoare

110

T FT', T' *FT' | , T -> T * F | T */ static void termen() { factor(); while (1) if (caracter_curent == '*') { gasit('*'); factor(); } else break; } /* F () | a */ static void factor() { if (caracter_curent == 'a') gasit('a'); else { gasit('('); expr(); gasit(')'); } } main() { caracter_curent = getchar(); expr(); putchar('\n'); }

Programul afieaz n ecou caracterele care sunt identificate drept corecte. n momentul n care se gasete un caracter care nu mai corespunde se afieaz mesajul de eroare. Se observ c abordarea anterioar presupune utilizarea unor proceduri recursive. Se poate ns implementa o abordare nerecursiv prin utilizarea unei stive. Adic, prin simularea explicit a unui automat cu stiv. Problema fundamental n timpul analizei predictive const din determinarea produciei care va fi utilizat pentru neterminalul curent. Dezavantajul analizei predictive const din faptul c prin transformarea gramaticilor i apoi prin transformarea diagramelor se poate pierde semnificaia producilor ceea ce poate complica pn la imposibil procesul de generare de cod.

3.1.1.2. Gramatici LL(1)

110

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

111

n cazul analizei LL(1) modelul analizorului este :


banda de intrare ----------------------------------------------------------------

| | | | | | | | | | | |

| cap de citire | | | | | +-----------+ | | analizor | |<----------| sintactic |---------- iesire | +-----------+ | | | +-----------+ | | tabela | | | de | | | analiza | | +-----------+

stiva

Este vorba de fapt de un automat cu stiv pentru care funcia de transfer m este memorat ntr-o tabel de analiz. Pentru a favoriza construirea unui automat determinist se consider c pe banda de intrare irul analizat este urmat de un simbol special care nu aparine gramaticii, pe care l vom nota cu $. Existnd un mecanism de identificare a sfritului irului se extinde clasa imbajelor care pot s fie acceptate de ctre automat. Stiva conine iniial simbolii S i $ unde S este simbolul de start al gramaticii memorat n vrful stivei. n orice moment stiva conine o secven de simboli terminali i neterminali. Tabela de analiza este o matrice M[A,a] unde A este un neterminal iar a este un terminal sau simbolul $. Programul care simuleaz funcionarea analizorului sintactic funcionez n modul urmtor. Fie X simbolul din vrful stivei i a simbolul curent pe banda de intrare. Exist trei posibiliti : 1. dac X = a = $ analiza s-a terminat cu succes; 2. dac X = a $ analizorul extrage simbolul a din vrful stivei i deplaseaz capul de citire pe banda de intrare cu o poziie la dreapta; 3. dac X este un neterminal, analizorul va cerceta valoarea M[X,a]. Valoarea din intrarea respectiva este fie o producie pentru neterminalul X fie o informaie de eroare. Dac de exemplu M[X,a] = {X UVW}, simbolul X din vrful stivei va fi inlocuit cu UVW ( U este noul vrf al stivei). Ca algoritm funcionarea analizorului poate s fie descris de urmtorul algoritm de simulare a unui automat push down determinist: Intrare un ir w i o tabela de analiz M pentru gramatica G. Iesire dac w L(G), derivarea stng, altfel un mesaj de eroare. Iniial configuraia automatului este w$ pe banda de intrare i S$ n stiv. Analizorul va afia produciile aplicate pe masur ce evolueaz. Avnd n vedere c nu este necesar dect o singur stare pentru unitatea de control a automatului aceasta nu mai este considerat explicit.
initializeaza vrful stivei intitializeaza pozitie curenta pe banda de intrare repeta

111

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

112

fie X simbolul din vrful stivei si a caracterul curent de pe banda de intrare daca X este un simbol terminal sau $ atunci daca X = a atunci descarca stiva actualizeaza pozitia curenta pe banda de intrare altfel eroare exit altfel /* X este un simbol neterminal */ daca M[X,a] contine X Y1 Y2 ... Yk atunci inlocuieste X din varful stivei cu Y1 Y2 ... Yk afiseaza productia X Y1 Y2 ... Yk altfel eroare exit

pana X = $ /* stiva este goala */

S relum exemplul gramaticii expresiilor aritmetice. Tabela de analiz corespunztoare acestei gramatici este :
neterminal a + * ( ) $ ----------+--------+--------+--------+--------+--------+--------| | -> TE'| | | -> TE'| | | ----------+--------+--------+--------+--------+--------+--------| ' | |'->+TE'| | |' |' | ----------+--------+--------+--------+--------+--------+--------| T |T -> FT'| | |T->FT' | | | ----------+--------+--------+--------+--------+--------+--------| T' | |T' |T'->*FT'| |T' |T' | ----------+--------+--------+--------+--------+--------+--------| F |Fa| | |F->() | | | ----------------------------------------------------------------+

Pentru irul a + a * a rezult urmtoarele micri (stiva este reprezentata cu vrful la stnga):
Stiva Intrare Iesire ------------+-----------------------+---------------------$ | a+a*a$ | ------------+-----------------------+---------------------TE'$ | a+a*a$ | TE' ------------+-----------------------+---------------------FT''$ | a+a*a$ | T FT' ------------+-----------------------+---------------------aT''$ | a+a*a$ | Fa ------------+-----------------------+---------------------T''$ | +a*a$ | ------------+-----------------------+----------------------

112

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

113

'$ | +a*a$ | T' ------------+-----------------------+---------------------+TE'$ | +a*a$ | ' +TE' ------------+-----------------------+---------------------TE'$ | a*a$ | ------------+-----------------------+---------------------FT''$ | a*a$ | T FT' ------------+-----------------------+---------------------aT''$ | a*a$ | Fa ------------+-----------------------+---------------------T''$ | *a$ | ------------+-----------------------+---------------------*FT''$| *a$ | T' *FT' ------------+-----------------------+---------------------FT''$ | a$ | ------------+-----------------------+---------------------aT''$ | a$ | Fa ------------+-----------------------+---------------------T''$ | $ | ------------+-----------------------+---------------------'$ | $ | T' ------------+-----------------------+---------------------$ | $ | ' -----------------------------------------------------------

Construcia tabelei de analiza este realizat cu ajutorul a doua funcii FIRST i FOLLOW. FIRST : (N T)* P(T {}) FOLLOW : N P(T {$}) Dac w este un ir de simboli w (N T)*, FIRST(w) reprezint setul terminalelor cu care ncep irurile derivate din w. Dac w * atunci FIRST(w). Pentru un neterminal A, FOLLOW(A) reprezint mulimea terminalelor a care pot s apar imediat dupa A ntr-o form propoziional; adica dac exist o derivare S * Aa atunci a FOLLOW(A). Pentru a calcula FIRST(X) pentru toi simbolii X din gramatic se aplic urmtoarele reguli pn cnd nu se mai pot aduga simboli terminali sau pentru nici o mulime FIRST(X). 1. Dac X este un terminal atunci FIRST(X) = {X}; 2. Dac exist o producie X atunci FIRST(X) = FIRST(X) {} 3. Dac exist o producie X Y1 Y2 ... Yk i a FIRST(Yi), FIRST(Y1), ..., FIRST(Yi-1), (Y1 Y2 ... Yi-1 * ) atunci a FIRST(X). Dac FIRST(Yj), 1 j k, atunci FIRST(X). (orice simbol terminal din FIRST(Y1) este inclus n FIRST(X). Dac Y1 * atunci i orice simbol terminal din FIRST(Y2) este inclus n FIRST(X), etc.). Putem s calculm funcia FIRST pentru orice ir X1 X2 ... Xm n modul urmtor. Se adaug la FIRST(X1 X2 ... Xm) toi simbolii diferiti de din FIRST(X1). Se adaug apoi toi simbolii din FIRST(X2) diferiti de dac FIRST(X1), etc. n final dac apare n FIRST(Xi), 1 i m, se adauga la FIRST(X1 X2 ... Xm).

113

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

114

Pentru a calcula FOLLOW(A) pentru A N se aplic urmtoarele reguli n mod repetat pn cnd nimic nu se mai poate adauga la mulimile FOLLOW: 1. $ face parte din FOLLOW(S) (S este simbolul de start al gramaticii); 2. Dac exist o producie A wB atunci FIRST() \ {} FOLLOW(B); 3. Dac exist o producie de forma A w B sau o producie A wB i FIRST() ( * ) atunci FOLLOW(A) FOLLOW(B) (B poate s apar i n alte contexte). S considerm de exemplu din nou gramatica fr recursivitate stnga pentru expresii aritmetice:
TE', ' +TE' | , T FT', T' *FT' | , F () | a. FIRST() = FIRST(T) = FIRST(F) = {(,a} FIRST(E') = {+,} FIRST(T') = {*,} FOLLOW() = FOLLOW(') = {),$} FOLLOW(T) = FOLLOW(T') = {+,),$} FOLLOW(F) = {+,*,),$}

Pentru construirea tabelei de analiz se utilizeaz urmtoarele reguli: Dac A w este o producie i a FIRST(w) atunci dac simbolul pe banda de intrare este a analizorul trebuie s nlocuiasc n stiv pe A cu w. Dac w * atunci A este nlocuit n stiv cu w numai dac a FOLLOW(A) (n particular simbolul a poate s fie $).

Rezult urmtorul algoritm pentru construcia tabelei :


initializare matrice M pentru fiecare p = A w P executa pentru fiecare a FIRST(w) T executa M[A,a] = M[A,a] {A w}

daca FIRST(w) atunci pentru fiecare b FOLLOW(A) executa /* b T {$} */ M[A,b] = M[A,b] {A w}

Aplicnd acest algoritm asupra gramaticii expresiilor aritmetice va rezulta tabela cu care a fost ilustrat funcionarea analizei predictive. S considerm ns i urmtoarea gramatic : S i t S S' | a, S' e S | , b. ( este vorba de gramatica care descrie instruciunea if). Pentru aceast gramatic rezult urmtoarea tabel de analiz:

114

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

115

neterminal a b e i t $ ----------+--------+--------+--------+---------+--------+--------| S | S -> a | | |S->iEtSS'| | | ----------+--------+--------+--------+---------+--------+--------| S' | | |S' -> | | |S' > | | | |S' -> eS| | | | ----------+--------+--------+--------+---------+--------+--------| | | > b | | | | | -----------------------------------------------------------------+

M[S',e] = {S' eS, S' } deoarece FOLLOW(S') = {e, $}. Se tie c n aceast form gramatica este ambigu i ambiguitatea se manifest prin alegerea ce trebuie s fie fcut cnd se ntlnete simbolul e (else). Soluia corect este de a alege producia S' eS (aceast alegere corespunde asocierii cuvintului else cu cel mai recent then). Se observ c alegerea permanent a produciei S' ar impiedica aducerea terminalului e (else) n vrful stivei ceea ce nu poate conduce la o evoluie corect. O gramatic pentru care n tabela de analiz nu exist intrri cu mai multe alternative se spune c este o gramatic LL(1) (primul L se refera la parcurgerea irului de intrare de la stnga (Left) la dreapta, al doilea L pentru utilizarea derivrii stnga (Left), iar 1 se refer la utilizarea unui terminal pentru a adopta o decizie de analiza). Gramaticile LL(1) sunt gramatici neambigue, nerecursive stnga i factorizate. Se poate arta c o gramatic G este LL(1) dac i numai dac pentru oricare doua producii de forma A , A , cu sunt satisfacute urmtoarele condiii : 1. FIRST() FIRST() = 2. dac * atunci FIRST() FOLLOW(A) = iar dac * atunci FIRST() FOLLOW(A) = . Gramatica pentru expresii aritmetice (fr recursivitate stnga) este LL(1) n timp ce gramatica considerat pentru instructiunea if nu este LL(1). Se pune problema cum se poate realiza o analiz predictiv pentru un limbaj descris de o gramatic care nu este LL(1). O solutie este de a transforma gramatica astfel nct s devin LL(1). n anumite cazuri (ca de xemplu n cazul anterior al gramaticii pentru limbajul corespunztor instruciunilor if) se poate face o "potrivire" a tabelei M, dar nu exist o regul general de transformare a matricii de analiz astfel nct intrrile multiple s poat s fie nlocuite cu intrri simple. Transformarea suferit de o gramatic pentru a deveni LL(1) o poate face ns dificil de recunoscut. De obicei analiza predictiv este utilizat pentru instruciuni (nu pentru expresii).

3.1.1.3. Tratarea erorilor n analiza predictiv


Existena n stiv a terminalelor i neterminalelor pe care analizorul se ateapt s le gseasc pe banda de intrare simplific mult problema diagnosticrii erorii. O eroare este detectat n timpul analizei dac n vrful stivei se gsete un terminal care nu coincide cu terminalul curent de pe banda de intrare, sau dac pentru neterminalul din vrful stivei (fie el A) i terminalul curent de pe banda de intrare (fie el a) n tabela M nu exist o producie (M[A,a] = ). Problema cea mai dificil nu este ns identificarea erorii ci stabilirea modului n care analiza trebuie s continue dup identificarea unei erori. Dac o astfel de continuare nu ar fi posibil atunci la prima eroare ntlnit compilatorul trebuie s abandoneze analiza. O metod posibil de 115

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

116

continuare n caz de eroare const din ignorarea de pe banda de intrare a simbolilor care urmeaz pn la ntlnirea unui simbol dintr-o mulime numit mulime de sincronizare. Aceast mulime se alege astfel nct analizorul s poat s decid ct mai rapid modul de continuare pentru erorile cele mai frecvente. Se utilizeaz n acest scop cteva reguli cu caracter euristic ca de exemplu : 1. Pentru un neterminal A aflat n vrful stivei mulimea de sincronizare va conine simbolii din FOLLOW(A). Dac la ntlnirea unui astfel de simbol pe banda de intrare se descarc stiva, exist o bun ans pentru continuarea analizei, ca i cum s-ar fi reuit identificarea simbolului A; 2. Pentru limbaje de programare care au caracter de terminare a instruciunilor (ca de exemplu ; pentru limbajul C) acestea vor fi considerate n mulimile de sincronizare pentru neterminalele care corespund instruciunilor. Pentru orice instruciune cuvintele cheie care nu fac parte din setul FOLLOW(instruciune) pot s fie introduse n mulimea de sincronizare. n acest caz dac de exemplu dup o instruciune de atribuire lipsete terminalul care indic terminarea acesteia n analiza se poate trece la cuvintul cheie care reprezint nceputul instruciunii urmtoare, etc. Pe de alt parte n general pentru o gramatic care descrie un limbaj de programare exist o ierarhie a construcilor sintactice. De exemplu expresiile apar n instruciuni care apar n blocuri care apar n funcii, etc. Rezult ca mulimea de sincronizare corespunztoare unei structuri sintactice va conine simbolii corespunztori structurilor superioare. Astfel, se vor aduga cuvintele cheie cu care ncep instruciunile la mulimea de sincronizare pentru neterminalele care genereaz expresii. 3. Dac se adaug simbolii din FIRST(A) la mulimea de sincronizare pentru A, atunci se poate relua analiza corespunztoare neterminalului A cu recunoaterea unui terminal din FIRST(A) la intrare. Utiliznd n caz de eroare dac este posibil pentru neterminalul aflat n vrful stivei o -producie se poate amna diagnosticarea erorii. 4. Dac pentru terminalul din vrful stivei nu exist o coresponden n irul de intrare se poate afia un mesaj corespunztor renunndu-se n continuare la simbolul respectiv. Utiliznd funciile FIRST i FOLLOW se poate completa tabela M cu informaiile referitoare la mulimea simbolilor de sincronizare. De exemplu pentru tabela de analiz corespunztoare gramaticii expresiilor aritmetice rezult:

| a | + | * | ( | ) | $ | sinc | ----+--------+--------+--------+------+--------+--------+------| | -> TE'| | |->TE'| sinc | sinc | ) $ | ----+--------+--------+--------+------+--------+--------+------| ' | |'->+TE'| | |' |' | ) $ | ----+--------+--------+--------+------+--------+--------+------| T |T -> FT'| sinc | |T->FT'| sinc | sinc |+ ) $ | ----+--------+--------+--------+------+--------+--------+------| T' | |T'-> |T'->*FT'| |T' -> |T' -> |+ ) $ | ----+--------+--------+--------+------+--------+--------+------| F | F -> a | sinc | sinc |F->()| sinc | sinc |+*)$ | ---------------------------------------------------------------+

116

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

117

Mulimile sinc sunt construite pornind de la funcia FOLLOW. Cu ajutorul unei tabele de acest tip analiza se va executa n modul urmtor . Dac M[A,a] nu conine nici o valoare atunci se avanseaz peste simbolul curent (a). Dac M[A,a] = sinc atunci se descarc vrful stivei pentru a continua analiza cu ce urmeaz dup simbolul din vrful stivei. Dac terminalul din vrful stivei nu se potrivete cu terminalul de la intrare se descarc terminalul din vrful stivei. De exemplu pentru secven de intrare : )a * + a se obine :
Stiva Intrare Iesire ------------+-----------------------+---------------------$ | )a*+a$ | eroare, ) FIRST() ------------+-----------------------+---------------------E$ | a*+a$ | ------------+-----------------------+---------------------TE'$ | a*+a$ | TE' ------------+-----------------------+---------------------FT''$ | a*+a$ | T FT' ------------+-----------------------+---------------------aT''$ | a*+a$ | Fa ------------+-----------------------+---------------------T''$ | *+a$ | ------------+-----------------------+---------------------*FT''$| *+a$ | T' *FT' ------------+-----------------------+---------------------FT''$ | +a$ | eroare ------------+-----------------------+---------------------T''$ | +a$ | T' ------------+-----------------------+---------------------'$ | +a$ | ' +TE' ------------+-----------------------+---------------------+T''$ | +a$ | ------------+-----------------------+---------------------T''$ | a$ | T' ------------+-----------------------+---------------------'$ | $ | ' ------------+-----------------------+---------------------$ | $ | -----------------------------------------------------------

Se observ c pentru nceput se caut un simbol din FIRST() pentru a ncepe recunoaterea ignorindu-se astfel terminalul ) i nu se descarc stiva. Pentru M[F,+] = sinc se va descrca stiva.

3.1.2. Analiza sintactica bottom-up 3.1.2.1. Analiza sintactica de tip deplaseaza i reduce
Analiza sintactica de tip bottom-up ncearc s construiasc un arbore de derivare pentru un ir de intrare dat pornind de la frunze spre rdcina aplicnd metoda "handle pruning". Adic trebuie s se construiasc n stiv partea dreapt a unei producii. Selecia produciei construite se face pe baza "nceputurilor" care reprezint nceputuri posibile de iruri derivate conform produciei respective.

117

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

118

3.1.2.2 Implementarea analizei sintactice bottom-up deplaseaz i reduce


Pentru a utiliza aceast metod trebuie s fie rezolvate dou probleme : 1. localizarea nceputului; 2. alegerea produciei (dac exist mai multe producii cu aceeai parte dreapta). Algoritmul de analiz sintactic de tip deplaseaz i reduce realizeaz simularea unui automat cu stiv. Din irul de intrare se mut simboli terminali n stiva pn cnd n vrful stivei se obine un nceput care este redus la partea stnga a uneia dintre produciile corespunztoare gramaticii. Dac iniial n stiv se gsete numai simbolul $ iar pe banda de intrare se gsete irul w$ n final dac w aparine limbajului acceptat de analizor, n stiv se va gsi $S (cu S vrful stivei, S - simbolul de start al gramaticii) iar pe banda de intrare capul de citire este poziionat pe simbolul $. S considerm de exemplu aciunile necesare pentru recunoaterea irului a + a * a pentru gramatica expresiilor aritmetice : + | * | a.
stiva | intrare | actiune -------------------+------------------+-------------------$ |a+a*a$ | deplaseaza -------------------+------------------+-------------------$a | +a*a$ | reduce a -------------------+------------------+-------------------$ | +a*a$ | deplaseaza -------------------+------------------+-------------------$ + | a*a$ | deplaseaza -------------------+------------------+-------------------$ + a | *a$ | reduce a -------------------+------------------+-------------------$ + | *a$ | deplaseaza -------------------+------------------+-------------------$ + * | a$ | deplaseaza -------------------+------------------+-------------------$ + * a | $ | reduce a -------------------+------------------+-------------------$ + * | $ | reduce * -------------------+------------------+-------------------$ + | $ | reduce + -------------------+------------------+-------------------$ | $ | succes -----------------------------------------------------------

Au fost utilizate 4 tipuri de operaii : 1. deplasare - presupune mutarea simbolului terminal curent de pe banda de intrare n vrful stivei; 2. reduce - n vrful stivei se gsete un nceput care va fi nlocuit cu partea stnga a produciei respective; 3. succes - s-a ajuns la sfritul irului i coninutul stivei este $S; 4. eroare.

118

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

119

Avantajul utilizrii stivei const din faptul c un nceput se formeaz ntotdeauna n vrful stivei (i deci dac nu s-a format n vrful stivei un nceput atunci acesta nu trebuie s fie cutat n alt parte). S considerm dou situaii care pot s apar n cazul derivrilor dreapta :
1. S * A z * B y z * y z 2. S * B x A z * B x y z * x y z

cu A B , A y, B , x,y,z T*, ,, (T N)+ n primul caz ( S * A z) reducerea inseamna :


stiva $ $B $By $A $Az $S intrare yz$ yz$ z$ z$ $ se se se se se reduce copiaza y reduce By copiaza z reduce aAz

n al doilea caz ( S * a B x A z).


stiva $ $B $Bx $Bxy $BxA $BxAz $S intrare xyz$ xyz$ yz$ z$ z$ $ se se se se se se reduce copiaza x copiaza y reduce y copiaza z reduce aBxAz

Se observ c ntotdeauna nceputul utilizat pentru reducere este n vrful stivei. Setul prefixelor derivrilor dreapta ce pot s apara n vrful stivei n analiza unui analizor de tip deplaseaz reduce se numete setul prefixelor viabile pentru gramatica respectiv. Exist gramatici independente de context pentru care nu se poate utiliza o analiz de tip deplaseaz i reduce, deoarece se poate ajunge fie n situaii n care nu se tie dac trebuie s se efectueze o deplasare sau o reducere (conflict reducere / deplasare) respectiv nu se tie care dintre variantele de reducere posibile trebuie s fie luat n considerare (conflict reduce / reduce). S considerm de exemplu din nou gramatica pentru instruciuni, n forma ambigu:
instr if expresie then instr | if expresie then instr else instr | alte_instr

Dac se ajunge n configuraia :


stiva ...if expresie then instr intrare else ... $

119

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

120

nu putem s hotrm dac if expresie then instr este un nceput indiferent de ce mai conine stiva. S observa ca n acest caz avem un conflict deplaseaza / reduce. Aceast gramatic i n general orice gramatic ambigu nu permite o analiz sintactic ascendent determinist. Pentru acest caz particular dac hotarm c n situaia unui conflict deplaseaza / reduce are prioritate deplasarea atunci se va ajunge la o execuie corect a analizei. S considerm i o gramatica care descrie instruciuni de atribuire i apeluri de funcii. n expresiile care apar n instruciunea de atribuire i n lista de parametri actuali ai unei proceduri pot s apar variabile simple sau elemente de variabilele indexate pentru care se utilizeaz paranteze obinuite. S considerm c analizorul lexical produce pentru atomul lexical identificator simbolul terminal id. Se obine urmtoarea gramatic :
instruciune id(lista_par) | expresie := expresie lista_par lista_par, id | id expresie id(lista_expr) | id lista_expr lista_expr, expresie | expresie

S considerm o instruciune care ncepe cu A(i,j) i deci care este de forma id(id,id). Se observ c se ajunge n configuraia:
stiva id ( id intrare , id ) ...

Se observ c nu se tie care este producia cu care se face reducerea pentru c simbolul neterminal la care se face reducerea depinde de tipul variabilei A (variabila indexata sau funcie). Rezult ca a aprut un conflict reduce-reduce. Aceasta informaie poate s fie obinut din tabela de simboli. O soluie const din modificarea analizorului lexical care poate s furnizeze terminale diferite pentru variabile indexate i nume de funcii. n acest caz alegerea reducerii se va face n funcie de tipul identificatorului care precede paranteza.

120

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

121

3.1.2.3. Analiza sintactica de tip LR(k)


LR(k) este o metod de analiz ascendent al crui nume are urmtoarea semnificaie : primul L indic sensul parcurgerii - stnga, dreapta, litera R indic faptul c derivarea este dreapta iar k indic numrul de atomi lexicali necesari pentru o alegere corecta a unui nceput stiv. Avantajele metodei LR(k) sunt : se pot construi analizoare de tip LR pentru toate construciile din limbajele de programare care pot s fie descrise de gramatici independente de context; clasa limbajelor care pot s fie analizate descendent n mod determinist este o submulime proprie a limbajelor care pot s fie analizate prin tehnici LR; detectarea erorilor sintactice se face foarte aproape de atomul lexical n legtura cu care a aparut eroarea.

Dezavantajul major al acestei metode - volumul mare de calcul necesar pentru implementarea unui astfel de analizor fr aportul unui generator automat de analizoare sintactice. S considerm din nou structura unui automat cu stiv.
banda de intrare ----------------------------------------------------------------

| | | | | | | | | | | |

| cap de citire | | | | | +-----------+ | | analizor | |<----------| sintactic |---------- iesire | +-----------+ | | | +-----------+ | | tabela | | | de | | | analiza | | +-----------+

Ca i n cazul analizei LL particularizarea limbajului se face prin intermediul tebelei de analiz care conine funcia m. nainte de a ncepe discuia referitoare la modul de construire a tabelelor de analiza este bine s reamintim cteva definiii. i anume se numete nceput al unei forme propoziionale partea dreapt a unei producii care dac este nlocuit cu partea stnga produce forma propoziional anterioar n irul formelor propoziionale obinute ntr-o derivare dreapta. Un prefix viabil este un subir cu care poate ncepe o form propoziional. Problema central n execuia algoritmului const din identificarea momentului n care n vrful stivei a fost obinut un nceput. Desigur, o variant posibil este explorarea complet a stivei la fiecare pas. Evident, o astfel de abordare este ineficient. n cazul analizei de tip LR(k) se utilizeaz pentru identificarea capetelor un dispozitiv similar cu un automat finit. Rolul acestui automat este de a controla activitatea de recunoatere a nceputurilor. S considerm de exemplu din nou gramatica expresiilor aritmetice :
(1) + T

121

Irina Athanasiu
(2) (3) (4) (5) (6) T T F F T T*F F () a

10/4/2003

Limbaje formale si translatoare

122

Putem s considerm diagrama de tranziii corespunztoare acestor producii:


+------+ +------+ +------+ +----+ | | + | | T |+----+| | |---| I1 |--- | I6 |--- || I9 || | | | | | | |+----+| | | +------+ +------+ +------+ | | +------+ +------+ +-------+ | | T |+----+| * | | F |+-----+| | |---|| I2 ||--- | I7 |--- || I10 || | | |+----+| | | |+-----+| | | +------+ +------+ +-------+ | | +------+ | | F |+----+| | I0 |---|| I3 || | | |+----+| | | +------+ | | +------+ +------+ +-------+ | |( | | | | ) |+-----+| | |---| I4 |--- | I8 |--- || I11 || | | | | | | |+-----+| | | +------+ +------+ +-------+ | | +------+ | | a |+----+| | |---|| I5 || | | |+----+| | | +------+ +----+

S urmrim secvena de stri prin care se trece pentru irul de intrare a * a + a.


+------+ +------+ | | a |+----+| | I0 |---|| I5 || | | |+----+| +------+ +------+ +------+ +------+ | | F |+----+| | I0 |---|| I3 || | | |+----+| +------+ +------+ a fost recunoscuta n starea 0 partea dreapta a productiei F a, cu alte cuvinte sirul de intrare este de forma F * a + a (deplasare pentru a, urmata de reducere cu F a) a fost recunoscuta n starea 0 partea dreapta a productiei T F, cu alte cuvinte sirul de intrare este de forma T * a + a (reducere pentru T F)

+------+ +------+ +------+ | | T | |* | |n acest moment la | I0 |---| I2 |--- | I7 |intrare urmeaz a + a

122

Irina Athanasiu
| | +------+ | | +------+

10/4/2003
| | +------+

Limbaje formale si translatoare

123

+------+ +------+ +------+ +------+ | | T | |* | | a |+----+|a fost recunos| I0 |--- | I2 |---| I7 |-- || I5 ||cuta n starea 7 | | | | | | |+----+|partea dreapta a +------+ +------+ +------+ +------+productiei F a

Cu alte cuvinte n starea 7 urmeaz irul de intrare F + a


+------+ +------+ +------+ +------+ | | T | |* | | F |+----+| | I0 |--- | I2 |---| I7 |--- || I10|| | | | | | | |+----+| +------+ +------+ +------+ +------+

A fost recunoscut n starea 0 partea dreapt a produciei T T * F (reducere).


+------+ +------+ a fost recunoscuta n starea 0 partea | | T |+----+| dreapta a productiei T, | I0 |---|| I2 || la intrare urmeaz sirul + a. | | |+----+| +------+ +------+ +------+ +------+ +------+ +------+ | | | |+ | | a |+----+|a fost recunos| I0 |--- | I1 |--- | I6 |---|| I5 ||cuta n starea 6 | | | | | | |+----+|partea dreapta a +------+ +------+ +------+ +------+productiei F a

Evoluia continu pn la obinerea situaiei :


+------+ +------+ | | | | | I0 |--- | I1 | | | | | +------+ +------+

Avnd n vedere aceasta evolutie diagrama de tranziii poate s fie reprezentat i sub forma urmtoare (n care se evideniaz toate nceputurile posibile) :

123

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

124

+------+ +------+ +----+ | | + +----+ T |+----+| * | |---| I1 |---- | |----|| I9 ||--- I7 | | | | | | |+----+| | | +------+ | | +------+ | | | |F | | | I6 |--- I3 | | | |( | | | |--- I4 | | | |a | | | |--- I5 | | +----+ | | +------+ +-------+ | | T |+----+| * +----+ F |+-----+| | |---|| I2 ||--- | |---- || I10 || | | |+----+| | | |+-----+| | | +------+ | I7 | +-------+ | | | |( | | | |---- I4 | I0 | | |a | | | |---- I5 | | +------+ +----+ | | F |+----+| | |---|| I3 || | | |+----+| | | +------+ | | - ( | | \/ +-------+ | | ( +----+ +----+ ) |+-----+| | |---| I4 |---- | |---- || I11 || | | +----+ | | |+-----+| | | | \\ | I8 | + +-------+ | | a | \\ T | |--- I6 | | V \\ | | | | +------+\\ +----+ | | a |+----+| \\- I2 | |---|| I5 || \ | | |+----+| \ F +----+ +------+ \- I3

Se utilizeaz convenia c la fiecare reducere se revine n starea anterioar lanului de arce corespunztoare nceputului identificat executndu-se o alt tranziie. Desenul anterior poate s fie interpretat ca reprezentnd un automat finit care accept nceputuri. S urmrim secven de stri prin care se poate trece pentru irul de intrare a * a + a :

124

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

125

a 0 --------- \\\ F \\ ------ \\ T \------ \ \ \ ---

5 3 * a 2 ---- 7 ----- 5 \ F ----- 10 + a 1 ---- 6 ----- 5 \\ F \----- 3 \T ---- 9

Se observ c pentru primul simbol a se ajunge n starea 5 n care s-a recunoscut partea dreapt a produciei F a, este ca i cum s-ar fi aplicat la intrare irul F * a + a, similar n acest caz se poate considera c s-a recunoscut partea dreapt a produciei T F. Dup T se gsete la intrare * apoi a, ajungndu-se n starea 5 n care se recunoate din nou partea dreapta a produciei F a. n acest moment n starea 10 s-a citit la intrare irul T * F deci se poate aplica pentru reducere producia T T * F. Un analizor sintactic LR realizeaz simularea acestor recunoateri de nceputuri memornd n stiv strile prin care se trece ntr-o recunoatere ca cea fcut anterior. Coninutul stivei la un moment dat este de forma s0 X1 s1 X2 s2 ... Xn sn, unde vrful stivei este sn ( de fapt n stiv este suficient s se memoreze numai starile nu i simboli Xi). Simbolii Xi reprezint simboli din gramatica iar si reprezint stri ale automatului care recunoate capete. Pe baza informaiei specificate de starea din vrful stivei i a simbolului curent de pe banda de intrare se determin micarea urmtoare efectuat de ctre analizor. Tabela de analiza este formata din doua parti : tabela de aciuni i tabela goto. Pentru o combinatie stare , simbol de intrare : sn, a, actiune[sn,a] poate avea urmtoarele valori : deplasare n starea s (se copiaz terminalul curent de pe banda de intrare n stiv i se trece n starea s). reduce pe baza productiei A , noua stare find determinat din tabela goto. succes eroare

Pentru o combintie (si, Xi), Xi N, goto[si, Xi] este starea automatului de recunoatere a nceputurilor n care se ajunge dac n starea si un nceput a fost redus la Xi. Configuraia unui analizor LR este dat de coninutul stivei i cel al benzii de intrare. Deoarece pe tot parcursul analizei automatul cu stiv se gsete n aceai stare, aceasta nu mai este prezentata explicit. Deci o configuraie este de forma :
(s0 X1 s1 X2 ... Xm sm, ai ai+1 ... an$)

unde X1 X2 ... Xm ai ai+1 ... an reprezint o form propoziional obinuta dintr-o derivare dreapta dac irul aflat iniial pe banda de intrare face parte din limbaj. Urmtoarea micare a analizorului depinde de ai i sm i este descris de actiune[sm,ai]. Modificrile posibile pentru configuraia automatului pot s fie :

125

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

126

dac aciune[sm,ai] = deplasare s, se obine noua configuraie : (s0 X1 s1 X2 ... Xm sm ai s, ai+1 ... an$)

dac aciune[sm,ai] = reduce pe baza A , se obine configuraia : (s0 X1 s1 X2 ... Xm-r sm-r A s , ai ai+1 ... an$) unde s = goto[sm-r,A] iar r este lungimea capatului utilizat pentru reducere. Se observ ca s-au eliminat 2 * r simboli din stiv, starea nou din vrful stivei fiind sm-r. Se introduce apoi n stiva neterminalul A (partea stnga a produciei) i starea obinuta pentru sm-r i A din tabela goto (s = goto[sm-r, A]).

dac aciune[sm,ai] = acc atunci analiza se ncheie. dac aciune[sm,ai] = eroare nseamn c s-a diagnosticat o eroare. Algoritmul general de analiza LR este : Intrare un ir de intrare w i o tabel de analiz LR. Iesire dac w L(G) este o propoziie derivata n G atunci se va obine lista produciilor aplicate ntr-o derivare dreapta, altfel se obine un mesaj de eroare corespunztor.
pozitioneaza ip pe inceputul sirului w$ si s0 n stiva. repeta fie s simbolul din vrful stivei si a simbolului de intrare curent dac actiune[s,a] = deplaseaza s' atunci memoreza a si s' n stiva ip++ altfel dac actiune[s,a] = reduce A atunci extrage 2 * || simboli din stiva fie s' noul vrf al stivei memoreaza A n stiva memoreaza goto[s',A] n stiva afiseaza producia A altfel dac actiune[s,a] = acc atunci return altfel eroare

pn false

S considerm de exemplu gramatica expresiilor artimetice :

(1) + T

126

Irina Athanasiu
(2) (3) (4) (5) (6) T T F F T T*F F () a

10/4/2003

Limbaje formale si translatoare

127

S considerm c vom utiliza tabela de analiz:


| actiune | goto | | stare | a | + | * | ( | ) | $ | | T | F | -------+---+---+---+---+---+---+---+---+---| 0 |s5 | | |s4 | | | 1 | 2 | 3 | -------+---+---+---+---+---+---+---+---+---| 1 | |s6 | | | |acc| | | | -------+---+---+---+---+---+---+---+---+---| 2 | |r2 |s7 | |r2 |r2 | | | | -------+---+---+---+---+---+---+---+---+---| 3 | |r4 |r4 | |r4 |r4 | | | | -------+---+---+---+---+---+---+---+---+---| 4 |s5 | | |s4 | | | 8 | 2 | 3 | -------+---+---+---+---+---+---+---+---+---| 5 | |r6 |r6 | |r6 |r6 | | | | -------+---+---+---+---+---+---+---+---+---| 6 |s5 | | |s6 | | | | 9 | 3 | -------+---+---+---+---+---+---+---+---+---| 7 |s5 | | |s4 | | | | | 10| -------+---+---+---+---+---+---+---+---+---| 8 | |s6 | | |s11| | | | | -------+---+---+---+---+---+---+---+---+---| 9 | |r1 |s7 | |r1 |r1 | | | | -------+---+---+---+---+---+---+---+---+---| 10 | |r3 |r3 | |r3 |r3 | | | | -------+---+---+---+---+---+---+---+---+---| 11 | |r5 |r5 | |r5 |r5 | | | | -------------------------------------------+

i - reprezint deplasare si starea urmtoare i rj - reprezint reducerea cu producia j acc - reprezint succes blanc - reprezint eroare

Tabela goto[X,a] este coninuta n tabela actiune[X,a] pentru a T. Fie irul de intrare a * a + a. Evoluia algoritmului de analiz este:
stiva | intrare | actiune ---------------+------------+----------------------------------0 | a * a + a $| deplasare ---------------+------------+----------------------------------0a5 | * a + a $| reduce cu F a (6), goto[0,F]=3 ---------------+------------+----------------------------------0F3 | * a + a $| reduce cu T F (4), goto[0,T]=2 ---------------+------------+----------------------------------0T2 | * a + a $| deplaseaza ---------------+------------+----------------------------------0T2*7 | a + a $| deplaseaza ---------------+------------+----------------------------------0T2*7a5| + a $| reduce cu F a (6),goto[7,F]=10 ---------------+------------+----------------------------------0 T 2 * 7 F 10| + a $| reduce cu T T * F (3) ---------------+------------+-----------------------------------

127

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

128

0T2 | + a $| reduce cu T (2), goto[0,]=1 ---------------+------------+----------------------------------01 | + a $| deplaseaza ---------------+------------+----------------------------------01+6 | a $| deplaseaza ---------------+------------+----------------------------------01+6a5| $| reduce cu F a (6), goto[6,F]=3 ---------------+------------+----------------------------------01+6F3| $| reduce cu T F (3), goto[6,T]=9 ---------------+------------+----------------------------------01+6T9| $| reduce cu + T (0) ---------------+------------+----------------------------------01 | $| succes ----------------------------------------------------------------

Problema cea mai dificil este desigur modul n care se construiesc tabelele de analiz. Se poate face urmtoarea observaie - evoluia analizorului urmrete recunoaterea nceputului din vrful stivei automatului. Dar o astfel de recunoatere poate s fie realizat de ctre un automat finit puin modificat. Simbolii de stare din stiv reprezint de fapt strile unui astfel de automat. Informaia din vrful stivei codific de fapt tot ce se gsete n stiv din punctul de vedere al nceputului construit. Se observ c deosebirea fundamental ntre analiza LL i analiza LR este c pentru analiza LL(k) pe baza a k atomi lexicali trebuie "ghicita" producia care se poate aplica pentru un simbol neterminal dat, pentru analiza LR(k) este cunoscut partea dreapta a productiei i trebuie "ghicita" producia pe baza urmtorilor k atomi lexicali care urmeaz. n cele ce urmeaz prezentam cteva metode de construire a tabelelor de analiza pentru analiza LR(1). 3.1.2.3.1. Analiza SLR Cea mai simpl metod de construire a tabelelor de analiza LR este metoda SLR (simple LR). Un element LR(0) pentru o gramatic G este o producie avnd un punct intercalat ntre simbolii parii dreapta ai produciei. Astfel din producia A XYZ rezult patru elemente : [A .XYZ], [A X.YZ], [A XY.Z], [A XYZ.]. Ideea utilizrii acestor elemente este c pentru a se recunoate nceputul XYZ se vor aduce pe rnd n vrful stivei prefixele X, XY, XYZ. Producia A produce un singur element [A .]. Un element poate s fie reprezentat de o pereche de numere. Primul reprezint numrul productiei, al doilea numr este poziia punctului. Semnificaia unui element este ct s-a recunoscut (vzut) din partea dreapta a unei producii. Ideea de baza este construirea unui automat finit determinist care s stie s recunoasc elemente LR. Se grupeaz elementele n mulimi care reprezint strile unui automat finit nedeterminist care recunoate prefixe viabile. Gruparea acestor elemente se face pe baza unui algoritm de construcie a subseturilor de tipul celor utilizate pentru construirea automatului finit determinist echivalent unui automat finit nedeterminist dat. O colecie a mulimilor de elemente LR(0) numit mulime canonic de elemente LR(0) reprezint punctul de plecare pentru construcia tabelelor de analiza. Pentru aceasta construcie se utilizeaz o gramatic modificat G', doua funcii : nchidere i goto i o procedur numit elemente. Gramatica G' se obine din G prin utilizarea unui alt simbol de start al gramaticii S' i a

128

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

129

unei producii S' S care permite recunoaterea strii de acceptare prin utilizarea n reducere a acestei producii. Dac I este o mulime de elemente pentru o gramatica G, atunci inchidere(I) este o mulime de elemente construite din I utiliznd urmtoarea funcie :
functia inchidere(I) este C=I repeta C' = C pentru fiecare A a . B B C executa /* B N */ fie B o productie pentru B C = C { [B .]} pna C = C' rezultat C

Dac A . B face parte din inchidere(I) la un moment dat n procesul de analiza, urmeaz s gasim la intrare un ir derivat din B. Corespunztor dac B este o producie, atunci n irul de intrare ne ateptm s gsim un ir derivat din . De exemplu pentru gramatica modificat a expresiilor aritmetice :
' T F +T|T T*F|F () | a

pornind de la setul I = {[' .]} se obine inchidere(I) :


' ., . + T, .T, T .T * F, T .F F .(), F .a

n general pentru o mulime T de elemente se poate face mprirea acestora n doua clase : 1. elemente care formeaz nucleul, din care se pot genera alte elemente. n aceasta clasa intr elementul S' .S i toate celelalte elemente din I care nu au punct pe prima poziie a prtii dreapta; 2. elemente care nu fac parte din nucleu i care au punct pe prima poziie a prii dreapta (cu excepia elementului S' .S). Se observ c orice element care nu face parte din nucleu poate s fie generat prin operaia de nchidere dintr-un element din nucleu. Corespunztor este suficienta memorarea numai a elementelor din nucleu (celelalte elemente putind s fie generate prin operatia de inchidere).
functia goto(I,X) este fie J = {[A aX.B] | [A a.XB] I} rezultat inchidere(J)

129

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

130

Funcia goto(I,X) unde I este o mulime de elemente (deci o stare a automatului finit utilizat n recunoaterea prefixelor viabile) i X N T, se definete ca fiind nchiderea tuturor elementelor [A a X. B] pentru care [A a . X B] este n I. Intuitiv, dac I este o mulime de elemente utilizate pentru prefixe de forma t, atunci goto(I,X) este mulimea de elemente utilizate pentru prefixul tX. De exemplu dac I = {[' .], [ . + T]} atunci goto(I,+) va conine {[ + .T], [T .T * F], [T .F], [F .()], [F .a]}. Se calculeaz goto(I,+) examinnd mulimea I pentru elemente avnd simbolul + dup punct. De exemplu elementul [' .] nu este un astfel de element n schimb se observ c elementul [ . + T] satisface condiia. Se va muta punctul peste simbolul + i se va obine elementul [ +. T] i se face nchiderea mulimii care conine acest element. Se poate construi mulimea canonic a mulimilor de elemente LR(0) pentru o gramatic G' modificat n modul urmtor :
procedura elemente C = {inchidere ({[S' .S]})} repeta C' = C pentru fiecare multime I C si fiecare X N T executa daca goto(I,X) & goto(I,X) C atunci C = C {goto (I,X)}

pana cand C = C'

Pentru gramatica expresiilor aritmetice s considerm din nou diagrama de tranziii pentru capetele care pot s apar n stiv:

130

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

131

+----+ +----+ + +----+ T +----+ * | |--- | I1 |---- | |----| I9 |--- I7 | | +----+ | | +----+ | | | |F | | | I6 |--- I3 | | | |( | | | |--- I4 | | | |a | | | |--- I5 | | +----+ | | T +----+ * +----+ F +-----+ | |--- | I2 |----| |---| I10 | | | +----+ | | +-----+ | | | I7 | ( | | | |---- I4 | I0 | | |a | | | |---- I5 | | +----+ | | F +----+ | |---| I3 | | | +----+ | | - ( | | \/ | | ( +----+ +----+ ) +-----+ | |---| I4 |---- | |----| I11 | | | +----+ | | +-----+ | | | \\ T | I8 | + | | a | \\ | |--- I6 | | V \\ +----+ | | a +----+ \\- I2 | |---| I5 | \ | | +----+ \F +----+ \- I3

Dac fiecare stare cu exceptia strii I0 este o stare final se observ c aceast diagram poate reprezenta automatul finit nedeterminist care accept prefixe viabile. Dac considerm automatul finit nedeterminist pentru care starile sunt elemente, se observ c va exista o tranziie de la nodul corespunztor elementului [A a.X ] la nodul corespunztor elementului A a X . . Aceasta tranziie (arc) va fi etichetat cu X. Exist o tranziie de la nodul corespunztor elementului [A a. B ] la nodul corespunztor elementului [B .] dac B este o producie. Acest arc va fi etichetat cu . Operaia de nchidere este de fapt operaia de construire a automatului finit determinist echivalent unui automat nedeterminist dat. n acest mod funcia goto(I,X) va indica tranziia din starea I pe baza simbolului X n automatul finit determinist. Rezult urmtoarea colecie canonica pentru G :
I0 : ' T T F . . + T .T .T * F .F .() I1 : ' I2: T I3 : T I4 : F . . + T T. T. * F F. (.) I5 : F a. I6 : + .T T .T * F T .F F .() F .a

131

Irina Athanasiu
F I9 : T I10: T I11: F .a + T. T. * F T * F. ().

10/4/2003
T T F F . + T .T .T * F .F .() .a

Limbaje formale si translatoare


I7 : T F F I8 : F T *. F .() .a (.) . + T

132

Spunem c elementul [A 1 . 2] este valid pentru un prefix viabil a 1 dac exist o derivare dreapta S * a A w * a 1 2 w. n general un element este valid pentru mai multe prefixe viabile. Dac A 1 . 2 este valid pentru a 1 i 2 atunci nu s-a gsit nc un capat deci urmtoarea operaie trebuie s fie o deplasare. Dac 2 = atunci se poate aplica pentru reducere producia A 1. Problema este c pentru acelai prefix se pot gsi mai multe elemente valide, deci n general poate s apar un conflict care eventual poate s fie soluionat pe baza urmtorului simbol de la intrare (LR(1)). Se poate demonstra c mulimea elementelor valide pentru un prefix viabil este mulimea elementelor care sunt parcurse pornind din starea iniial de a lungul unei ci etichetate cu n automatul finit determinist construit din mulimea canonic de mulimi de elemente cu tranziii date de funcia goto. De fapt aceste elemente valide conin toate informaiile necesare referitoare la coninutul stivei. S considerm din nou gramatica expresiilor aritmetice. Se observ c + T * este un prefix viabil. Automatul se va gasi n starea I7 dupa parcurgerea acestui prefix. Starea I7 conine elementele : [T T *. F], [F .()], [F .a]. S considerm de exemplu urmatoarele derivari dreapta :
' ' T T*F T*a T*F*a ' +T +T +T*F +T*F + T * () +T*a

+ + + +

Pentru prima derivare se va folosi elementul T T *. F, pentru a doua F .() iar pentru ultima F .a pentru prefixul viabil + T *. Construirea tabelelor de analiza SLR se face pornind de la automatul finit care accept prefixe viabile. Algoritmul care va fi prezentat n continuare nu produce n mod necesar tabele cu intrri coninnd un singur termen pentru orice gramatic care descrie un limbaj de programare dar poate s fie utilizat cu succes pentru majoritatea construciilor din limbajelor de programare. Dndu-se o gramatica G se utilizeaz gramatica G' (obinut prin nlocuirea simbolului de start al gramaticii S cu un simbol S' i adugarea produciei S' S) pentru a construi C, mulimea canonic de mulimi de elemente pentru G'. Algoritmul care produce tabelele de actiune i goto utilizeaz urmtorul algoritm :
Intrare O gramatica G' Iesire Tabele de analiza pentru G'

Algoritmul parcurge urmatoarele etape :


1. se construieste C = {I0, I1, ..., In} elemente LR(0) pentru G'. multimea canonic a multimilor de

132

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

133

2. starea i este corespunzatoare multimii Ii. Intrarile n tabela actiune pentru starea i se obtin n modul urmator : a) daca [A a . a ] Ii si goto(Ii,a) = Ij atunci actiune[i,a] = "deplaseaza j" /* a T */ b) daca [A a.] Ii & A S' atunci pentru fiecare a FOLLOW(A) executa actiune[i,a] = "reduce A a"

c) daca [S' S.] Ii atunci actiune [i,$] = "succes"

Dac n construirea tabelei actiune apar conflicte gramatica utilizata o alta metoda.

nu este SLR(1) i trebuie s fie

1. Intrarile n tabela goto pentru starea i se obzin n modul urmator : daca goto (Ii,A) = Ij /* tranzitia din starea Ii n starea Ij se face pentru simbolul A */

atunci goto[i,A] = j

4. Toate intrarile necompletate prin regulile 2 si 3 sunt marcate cu eroare 5. Starea initiala a analizorului este cea care corespunde multimii de elemente care contine elementul [S' .S].

Tabelele de analiz construite conform regulilor anterioare formeaza tabela SLR(1) pentru G. Un analizor LR care lucreaza cu tabele SLR(1) este un analizor SLR(1). S construim de exemplu analizorul SLR(1) pentru gramatica expresiilor aritmetice. S considerm nti mulimea I0 :
' ., . + T, .T, T .T * F, T .F, F .(), F .a.

Din elementul F .() se obine actiune[0,(] = "deplasare 4", din F .a se obine actiune[0,a] = "deplasare 5". Celelalte elemente nu produc aciuni. Pentru I1: ' ., . + T se obine actiune[1,$] = "succes", actiune[1,+] = "deplasare 6". I2 este format din T., T T. * F. FOLLOW() = {$,+,)}, rezult actiune[2,$] = actiune[2,+] = actiune[2,)] = "reduce T". Pentru T T. * F se obine actiune[2,*] = "deplasare 7". Coninnd se obine tabela utilizat pentru a ilustra funcionarea algoritmului de analiza LR. Orice gramatica SLR este neambigua. Reciproca nu este adevrat. S considerm de exemplu gramatica : (1) S L = R (2) S R

133

Irina Athanasiu (3) L *R (4) L a (5) R L

10/4/2003

Limbaje formale si translatoare

134

Mulimea canonic de mulimi de elemente este :


I0 : S' .S S .L = R S .R L .* R L .a R .L I1: S' S. I2: S L. = R R L. I3: S R. I4: L *.R R .L L .*R L .a I5: L a. I6: S L = .R R .L L .*R L .a I7: L *R. I8: R L. I9: S L = R.

Diagramele de tranziie pentru prefixele viabile sunt :

134

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

135

+------+ +----+ S |+----+| | |---|| I1 || | | |+----+| | | +------+ | | L +----+ +----+ a | |---| I2 |----- | |---- I5 | | +----+ | |R +----+ | | | |-----| I9 | | | | I6 | +----+ | | | |L +----+ | | | |-----| I8 | | | | |* +----+ | | | |----- I4 | | +----+ | | +------+ | | R |+----+| | I0 |---|| I3 || | | |+----+| | | +------+ | | * ___ | | \/ | | * +----+ | |---| | | | | |R +----+ | | | |-----| I7 | | | | I4 | +----+ | | | |L | | | |----- I2 | | +----+ | | Va | | a +----+ | |---| I5 | | | +----+ +----+

S considerm elementul I2 pentru care se obine actiune[2,=] = "deplasare 6". FOLLOW(R) FOLLOW(L) FOLLOW(R) deci FOLLOW(R) = FOLLOW(L), = FOLLOW(L), deci = FOLLOW(R) i deci actiune[2,=] = "reduce R L. Se observa c dei gramatica nu este ambigu a aprut un conflict deoarece metoda folosita nu este suficient de puternica neputnd s memoreze suficienta informaie pe baza creia pentru terminalul = s se stabileasca ce aciune trebuie s se execute pentru un ir care poate s fie redus la L. 3.1.2.3.2. Analiza canonica LR Prezentm n continuare metoda cea mai generala de construire a tabelelor LR(1) pentru o gramatic dat. Pentru metoda considerata anterior n starea i se face reducere cu producia A dac mulimea Ii conine elementul [A .] i a FOLLOW(A) urmeaz n irul de intrare. Exist situatii, n care dac i apare n vrful stivei, prefixul din stiva este astfel nct A nu poate s fie urmat de a ntr-o derivare dreapta i deci nu se poate face reducerea A . Relund ultimul exemplu pentru starea I2 i elementul [R L.], cu = pe banda de intrare, sa obinut = FOLLOW(R) i deci se pune problema aplicrii reducerii R L (vrful stivei conine L). Dar nu exist nici o derivare dreapta care s nceapa cu R = .... Deci nu trebuie 135

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

136

aplicat reducerea. Se observ c utilizarea condiiei a FOLLOW(A) este prea slab n cazul general. O soluie este transformarea gramaticii astfel nct pentru automatul care rezult s fie bine precizat ce simbol de intrare poate s urmeze unui capt pentru care exist posibilitatea unei reduceri. Alt soluie const din adugarea unei informaii pentru fiecare element obtinndu-se elementele LR(1). Informaia suplimentar este incorporat n stare prin redefinirea elementelor astfel nct fiecare element s conin ca a doua component un simbol terminal. Forma general pentru un element este: [A . , a] cu A o producie i a T {$}. Un astfel de obiect se numeste element LR(1). 1 se refer la numrul de simboli terminali luai n considerare pentru a se decide e4fectuarea unei reduceri. Pentru un element de forma [A ., a] se va face o reducere utiliznd producia A dac i numai dac urmtorul simbol de intrare este a. Dac un element este de forma [A . , a] i atunci a nu ofer o informaie suplimentara. Pentru elementele [A ., a] este clar c a FOLLOW(A) dar nu toate elementele din FOLLOW(A) apar n elementele LR(1) de forma [A .,a]. Se spune ca elementul LR(1) [A . ,a] este valid pentru un prefix viabil dac exist o derivare : S * Aw w, unde 1. = i 2. fie a este primul simbol din w, fie w = i a = $. Se considerm de exemplu gramatica S BB, B aB | b. Fie derivarea S aaBab aaaBab. Elementul [B a.B,a] este valid pentru prefixul viabil aaa considernd = aa, A = B w = ab, = a, = B n definiia anterioar. De asemenea s considerm i derivarea S + BaB BaaB. Pentru aceasta derivare elementul [B a . B, $] este valid pentru prefixul Baa. Metoda de construire a mulimii de elemente LR(1) valide este aceai cu cea pentru construirea mulimii canonice de mulimi de elemente LR(0) cu modificri adecvate ale procedurii inchidere i goto. S considerm un element de forma [A . B , a], A , B N, , (N T)*, a T. Acest element este valid pentru un prefix , dac exist o derivare dreapta S Aax Bax cu = . S presupunem c x by, b T , y T*. Atunci pentru orice producie B , vom avea derivarile S Bby by. Deci, [B ., b] este valid pentru . Se poate observa c b este primul simbol terminal derivat din , sau dac , x by i deci b = a. Altfel spus b FIRST(ax) (FIRST(ax) = FIRST(a), a ). Rezult urmatorul algoritm de construire a elementelor LR(1) : Intrare O gramatica G' Ieire mulimile de elemente LR(1) valide pentru unul sau mai multe prefixe din G'. Algoritmul utilizeaz urmtoarele proceduri auxiliare :

136

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

137

functia inchidere(I) este repeta I' = I pentru fiecare element [A . B , a] I, fiecare productie B , fiecare b FIRST(a) executa dac [B .,b] I atunci I = I {[B .,b]}

pana I = I' rezultat I

functie goto(I,X) este fie J = {[A X.,a] | [A .X,a] I} rezultat inchidere(J) procedura elemente(G') C = {inchidere ( { [S' .S,$]})}. repeta C' = C pentru fiecare I C, fiecare X N T executa daca goto(I,X) si goto(I,X) C atunci C = C {goto(I,X)}

pana C' = C

S considerm de exemplu gramatica S' S, S CC, C cC | d. Limbajul generat este cndcmd S calculm nti mulimea ({[S' .S, $]}. S identificam n elementul [S' .S,$] componentele elementului generic [A .B,a]. Rezult A = S', a = , B = S, = , a = $. Din modul de aciune al funciei inchidere se observ c se adaug termeni de forma [B ., b] pentru fiecare producie de forma B i fiecare b FIRST(a). Singura producie care se potriveste este S CC, pentru care a =$, pe post de b se obine $. Rezult adugarea elementului [S .CC, $] la mulimea inchidere ([{[S' .S,$]}. S considerm acum produciile care au C n partea stng pentru care trebuie s se adauge elementele [C .,b] pentru b FIRST(C$). Comparnd din nou elementul [S .CC,$] cu [A .B,a], de data aceasta A = S, = , B = C, = C, a = $. Deoarece C , FIRST(C$) = FIRST(C) = {c, d}. Se vor adauga deci elementele [C .cC, c], [C .cC,d], [C .d,c], [C .d, d]. Se observ c nu mai exist elemente cu un neterminal la dreapta punctului deci s-a obinut :
I0 : S' S C C .S,$ .CC,$ .cC,c/d .d, c/d

S calculm goto(I0,X) pentru diferitele valori posibile pentru X. Dac X = S se va calcula inchiderea elementului [S' S., $]. Rezult :

137

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

138

I1 : S' S.,$

Dac X = C vom calcula nchiderea pentru S C . C, $:


I2 : S C.C,$ C .cC,$ C .d,$

Dac X = c, se calculeaz nchiderea pentru {[C c.C, c/d]}.


I3 : C c.C, c/d C .cC, c/d C .d,c/d

Pentru X = d
I4 : C d., c/d

n acest mod s-a terminat calculul pentru inchidere (I0), urmeaz:


I5: S I6: C C C CC.,$ c.C,$ .cC,$ .d, $ I7: C d.,$ I8: C cC., c/d I9: C cC.,$

Rezult urmtorul graf al automatului :

138

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

139

+----+ S +----+ | |----| I1 | | | +----+ | | | | C +----+ C +----+ | |----| |-----| I5 | | | | | +----+ | | | | c ___ | | | | \/ | | | I2 | c +----+ C +----+ | | | |-----| I6 |---| I9 | | | | | +----+ +----+ | | | | \|/ d | | | | d +----+ | | | |-----| I7 | | I0 | +----+ +----+ | | c ___ | | \/ | | c +----+ C +----+ | |----| I3 |---| I8 | | | +----+ +----+ | | d | | | \|/ | | d +----+ | |----| I4 | | | +----+ +----+

Pe baza descrierii obinute pentru automatul finit, descriere ce s-a construit utiliznd funciile goto i inchidere, rezult urmatorul algoritm de construire a tabelelor de analiz LR pentru G'. Intrare o gramatica G' Iesire Tabelele de analiza actiune i goto pentru G' Algoritmul parcurge urmatoarele etape :
1. se construieste C = {I0, .., In} multimea de multimi canonice de elemente LR(1) pentru G'. 2. pentru fiecare stare i reprezentata prin multimea Ii executa dac [A .a , b] Ii si goto(Ii,a) = Ij /* a T */ atunci actiune[i,a] = "deplaseaza j" dac [A a., a] Ii, A S' atunci actiune[i,a] = "reduce A a" daca [S' S., $] Ii atunci actiune[i,$] = "succes"

Dac din cele regulile anterioare rezult un conflict atunci nseamn c gramatica nu este LR(1) i execuia algoritmului se oprete.
3. pentru fiecare Ii C si fiecare A N executa

139

Irina Athanasiu
daca goto(Ii,A) = Ij atunci goto [i,A] = j

10/4/2003

Limbaje formale si translatoare

140

4. Toate intrarile necompletate corespund unor situatii de eroare 5. Starea initiala a analizorului se obtine din multimea care contine elementul [S' .S,$].

Aplicnd acest algoritm pentru gramatica care are produciile : (1) S CC (2) C cC (3) C d se obin tabelele de analiza :
stare | actiune | goto | | c d $ | S C | -------+---------------+-----------| 0 | s3 s4 | 1 2 | -------+---------------+-----------| 1 | succes | | -------+---------------+-----------| 2 | s6 s7 | 5 | -------+---------------+-----------| 3 | s3 s4 | 8 | -------+---------------+-----------| 4 | r3 r3 | | -------+---------------+-----------| 5 | r1 | | -------+---------------+-----------| 6 | s6 s7 | 9| -------+---------------+-----------| 7 | r3 | | -------+---------------+-----------| 8 | r2 r2 | | -------+---------------+-----------| 9 | r2 | | -----------------------------------+

O gramatic SLR(1) este evident o gramatica LR(0), dar tabela de analiz LR(1) pentru aceai gramatic are mai multe stri dect tabela de analiza SLR. S relum i exemplul care "nu a funcionat" corect pentru algoritmul SLR: (1) S L = R (2) S R (3) L *R (4) L a (5) R L Mulimea canonic de mulimi de elemente este :
I0 : S' .S, $ S .L = R, $ S .R, $ I5: L a., =/$ I6: S L = .R, $ R .L, $

140

Irina Athanasiu
L .* R, =/$ L .a, =/$ R .L, $ S' S., $ S L. = R , $ R L., $ S R., $ L *.R, =/$ R .L, =/$ L .*R, =/$ L .a, =/$

10/4/2003

Limbaje formale si translatoare

141

I1: I2: I3: I4:

L .*R, $ L .a, $ I7: L *R., =/$ I8: R L., =/$ I9: S L = R. , $ I10: R L., $ I11: L *.R, $ R .L, $ L .*R, $ L .a, $ I12:L a., $

Se observ c pentru I2 se va face reducere dac urmeaz sfritul irului respectiv se va face deplasare dac urmeaz =. 3.2.5.3. Analiza sintactic LALR Numele LALR a fost ales pornind de la termenul "lookahead" - LR. Tabelele construite utiliznd aceasta metoda sunt mai mici (exist mai puine stri) dect tabelele canonice LR i de asemenea majoritatea construciilor din limbajele de programare pot s fie exprimate convenabil utiliznd gramatici LALR. Pentru un limbaj cum este PASCAL-ul tabelele de analiza LALR i SLR au sute de intrari n timp ce tabelele canonice au cteva mii. S relum din nou gramatica G' : S' S, S CC, C cC | d i s analizm mulimile canonice I4 i I7 :
I4 : C d., c/d , I7 : C d., $

Pentru I4 decizia de reducere este pentru simbolii terminali c i d, pentru I7 decizia de reducere se face pentru $. Gramatica pe care am considerat-o genereaz iruri de forma c*dc*d. Deci analizorul va deplasa iniial irul de c i va intra n starea I4 dup ntlnirea simbolului d, dup care se va face o reducere C d dac se ntlnete un c sau un d. Reducerea este corect deoarece c sau d pot s nceap irul c*d care trebuie s urmeze. Dac ns apare $ nseamn c irul s-a terminat prea devreme (de exemplu este de forma ccd). Dup d se intr n starea 7 dup care trebuie s urmeze $ sau irul de intrare nu este corect. S considerm ca reunim cele doua stri sub forma unui element [C d., c/d/$]. Trimiterile n I4 pentru d din I0, I2, I3 i I6 vor fi spre I47. Actiunea din I47 va fi de reducere pentru orice intrare. Deci exist situaii n care n loc de semnalarea unei erori se va face reducerea C d. De exemplu pentru irurile ccd sau cdcdc. Eroarea se va depista nainte de a se mai considera un alt caracter de intrare. n general se cauta mulimi de elemente LR(1) avnd acelai nucleu (aceeai mulime a primelor componente pentru elemente) i se face o reuniunea acestor mulimi de elemente. Pentru exemplul considerat mulimile I4 i I7 au ca nucleu mulimea {C d.}, de asemenea mulimile I3 i I6 au ca nucleu mulimea {C c.C, C .cC, C .d}. n general un nucleu este o mulime de elemente LR(0). O gramatica LR(1) poate produce mai multe mulimi cu acelai nucleu. Se observ c miezul mulimii goto(I,X) depinde numai de miezul mulimii I. Corespunztor se poate face reuniunea mulimilor goto pentru doua mulimi care au acelai nucleu. Valorile din tabela goto i actiune vor reflecta aceste reuniuni prin modificri corespunztoare. Adic tabela goto va reflecta noile mulimi ntre care se fac tranziii iar n tabela actiune se nlocuiesc o serie de intrri de eroare cu intrri de reducere.

141

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

142

S presupunem ca s-a construit o gramatica LR(1) fr conflicte. Dac nlocuim toate mulimile cu acelai nucleu cu reuniunea lor s-ar putea, dar este puin probabil s apar conflicte. S presupunem ca exist un conflict datorit unui simbol a T deoarece exist un element [A ., a] care indic o reducere cu A i exist un alt element [B . , b] care indic o deplasare. Se observ c n acest caz dintre elementele pentru care s-a facut reuniunea exist i elementele [A ., a] i [B ., b] pentru un anumit b. Inseamn c aceste elemente prezint acelai conflict deplaseaza / reduce pentru terminalul a i gramatica nu ar mai fi LR(1) asa cum s-a presupus. Deci un conflict deplaseaza / reduce nu poate s apar prin reuniunea mulimilor de elemente cu acelai nucleu, dac un astfel de conflict nu a aprut ntr-una din strile iniiale deoarece deplasrile depind numai de nucleu, nu i de simbolii care urmeaz pe banda de intrare. Dar poate s apar un conflict reduce / reduce. S considerm de exemplu gramatica : S' S, S aAd | bBd | aBe | bAe, A c, B c. Aceast gramatic genereaz irurile : acd, ace, bcd, bce. Construind mulimea elementelor LR(1) se va obine mulimea { [A c.,d], [B c., e]} ale carui elemente sunt valide pentru prefixul ac i mulimea {[A c., e], B c.,d]} ale crui elemente sunt valide pentru prefixul bc. Dac se construiete reuniunea acestor mulimi se obine mulimea {[A c., d/e], [B c., d/e] pentru care se observ c exist un conflict reduce/reduce. Acest conflict semnific faptul c gramatica nu este LALR(1). De obicei transformri asupra gramaticii rezolva problema.

142

Irina Athanasiu

10/4/2003

Limbaje formale si translatoare

143

Bibliografie Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman, Compilers Principles, Techniques, and Tools, Addison Wesley, 1986 Alfred V. Aho, Jeffrey D. Ullman, The Theory of Parsing, Translation and Compiling, Prentice- Hall William M. Waite, Gerhard Goos, Compiler Construction, Springer Verlang Harry R. Lewis, Christos H. Papadimitriou, Elements of the Theory of Computation, Prentice Hall, 1981 Michael A. Harrison, Introduction to Formal Language Theory

143

S-ar putea să vă placă și