You are on page 1of 144

Irina Athanasiu

3/1/2002

Limbaje formale i automate

1
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9

INTRODUCERE - ORGANIZAREA UNUI COMPILATOR................................ 2


Analiza lexicala ......................................................................................................................................... 4 Analiza sintactic ...................................................................................................................................... 4 Analiza semantic ..................................................................................................................................... 5 Generarea de cod intermediar................................................................................................................. 5 Optimizarea codului intermediar............................................................................................................ 5 Generarea codului obiect ......................................................................................................................... 6 Optimizarea codului obiect...................................................................................................................... 6 Gestiunea tabelei de simboluri ................................................................................................................ 6 Detectarea erorilor ................................................................................................................................... 6

ELEMENTE DE TEORIA LIMBAJELOR FORMALE........................................ 7

2.1 Gramatici .................................................................................................................................................. 7 2.1.1 Ierarhia Chomsky............................................................................................................................... 8 2.1.1.1 Exerciii ........................................................................................................................................ 9 2.1.2 Verificarea limbajului generat de ctre o gramatic ........................................................................ 10 2.1.2.1 Exerciii ...................................................................................................................................... 11 2.1.3 Transformri asupra gramaticilor independente de context............................................................. 11 2.1.3.1 Eliminarea ambiguitii............................................................................................................... 12 2.1.3.2 Eliminarea - produciilor .......................................................................................................... 16 2.1.3.3 Eliminarea recursivitii stnga................................................................................................... 16 2.1.3.4 Factorizare stnga ....................................................................................................................... 18 2.1.3.5 Eliminarea simbolilor neterminali neutilizai.............................................................................. 19 2.1.3.6 Substituia de nceputuri(corner substitution)............................................................................. 20 2.1.4 Construcii dependente de context................................................................................................... 22 2.1.4.1 Exerciii ...................................................................................................................................... 23 2.1.5 Proprieti ale limbajelor independente de context.......................................................................... 24 2.1.5.1 Exerciii ...................................................................................................................................... 25 2.2 Mulimi regulate, expresii regulate. ...................................................................................................... 25

2.3 Acceptoare............................................................................................................................................... 28 2.3.1 Automate finite ................................................................................................................................ 29 2.3.1.1 Construcia unui automat finit nedeterminist care accept limbajul descris de o expresie regulat dat 30 2.3.1.2 Conversia unui automat finit nedeterminist (AFN) ntr-un automat finit determinist(AFD)...... 34 2.3.1.3 Construcia unui automat finit determinist care accept limbajul descris de o expresie regulat dat 37 2.3.1.4 Simularea unui automat finit determinist.................................................................................... 43 2.3.1.5 Simularea unui automat finit nedeterminist ................................................................................ 44 2.3.1.6 Probleme de implementare pentru automatele finite deterministe i nedeterministe.................. 45 2.3.1.7 Minimizarea numrului de stri pentru AFD.............................................................................. 46

Irina Athanasiu

3/1/2002

Limbaje formale i automate

2.3.2 Automate cu stiv (pushdown) ........................................................................................................ 49 2.3.2.1 Automate cu stiv cu acceptare prin stiv goal ......................................................................... 52 2.3.2.2 Relaia ntre automate cu stiv i limbajele independente de context......................................... 53 2.3.3 Maina Turing.................................................................................................................................. 57 2.3.3.1 Calcule realizate de Maina Turing ............................................................................................ 60 2.3.3.2 Compunerea mainilor Turing .................................................................................................... 63 2.3.3.3 Extensii pentru maina Turing.................................................................................................... 67 2.3.3.4 Automate liniar mrginite ........................................................................................................... 73 2.3.3.5 Relaia ntre maina Turing i gramatici ..................................................................................... 74 2.3.3.6 Elemente de calculabilitate ......................................................................................................... 77 2.3.3.6.1 Maina Turing Universal ................................................................................................... 77 2.3.3.7 . Maina Turing cu limit de timp............................................................................................... 81

3
3.1 3.2

2. ANALIZA LEXICAL .................................................................................. 83


Interfaa analizorului lexical ................................................................................................................. 87 Un exemplu elementar de analizor lexical............................................................................................ 89

ANALIZA SINTACTIC .................................................................................. 99

4.1 Analiza sintactica top - down............................................................................................................... 103 4.1.1 Analiza sintactica predictiva (descendent recursiva) ..................................................................... 104 4.1.1.1 Gramatici LL(1)........................................................................................................................ 109 4.1.1.2 Tratarea erorilor n analiza predictiv ....................................................................................... 115 4.1.2 Analiza sintactica bottom-up ......................................................................................................... 117 4.1.2.1 Analiza sintactica de tip deplaseaza i reduce .......................................................................... 117 4.1.2.2 Implementarea analizei sintactice bottom-up deplaseaz i reduce .......................................... 117 4.1.2.3 Analiza sintactica de tip LR(k) ................................................................................................. 121 4.1.2.3.1 Analiza SLR ...................................................................................................................... 129 4.1.2.3.2 Analiza canonica LR ......................................................................................................... 136 4.1.2.3.3 Analiza sintactic LALR ................................................................................................... 142

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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

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

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 main

Preprocesorul realizeaz activiti de tip macro substituie, eliminarea comentariilor, 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 mbuntirii 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 forma unor proceduri ori funcii distincte ci

Irina Athanasiu

3/1/2002

Limbaje formale i automate

sunt realizate printr-un ansamblu de funcii care coopereaz. n cele ce urmeaz aceste componente vor fi descrise separat pentru simplificarea expunerii.
1.1 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 fiind 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 cuvntului cheie while exist un singur ir de intrare, pentru atomul lexical corespunztor unui numr ntreg pot s existe foarte multe iruri de intrare. Una dintre deciziile 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 aceeai prioritate i asociativitate pot s fie grupai mpreun. 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 relaionali 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 interacioneaz 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.
1.2 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

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 unitilor 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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

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 nregistrri) sau poate s sintetizeze informaiile din care se poate face construcia acestuia.
1.3 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 construciilor. De asemenea aceast faz completeaz arborele de derivare cu o serie de informaii necesare generrii de cod.
1.4 Generarea de cod intermediar

Nici aceasta faz nu este ntotdeauna 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 optimizri 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 aceleai 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.
1.5 Optimizarea codului intermediar

Aceast faz identific optimizrile posibile asupra codului n limbaj intermediar. De exemplu pentru o secven ca:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

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.
1.6 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.
1.7 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.
1.8 Gestiunea tabelei de simboluri

n tabela de simboluri 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 simboluri este o structur de date care conine cte o nregistrare pentru fiecare identificator avnd cmpuri pentru atributele posibile. Introducerea simbolurilor n tabela se face de ctre analizorul lexical. Atributele acestora sunt completate n tabela de ctre analizoarele sintactic i semantic.
1.9 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;

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 apar 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 dup identificarea unei erori, pentru c un compilator care se oprete la prima eroare ntlnit 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

Elemente de teoria limbajelor formale

Fie T o mulime de simboluri 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 cror 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 bijecie 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 ntr-un 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.
2.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 produciilor 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);

Irina Athanasiu

3/1/2002

Limbaje formale i automate

literele mari de la nceputul alfabetului latin (A, B, C,...) reprezint elemente din N (simboli neterminali); literele mari de la sfritul alfabetului latin (U, 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 obinndu-se derivarea n k pai. i anume k dac exist 0, 1, ..., k forme propoziionale astfel nct = 0, i-1 i ,1 i k i k = . nchiderea tranzitiv a relaiei se noteaz cu + . nchiderea 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:
S 0S0 00S00 001A100 0011A1100 00111100

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


2.1.1 Ierarhia Chomsky.

Noam Chomski este lingvist i lucreaz 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 produciilor n urmtoarea ierarhie : gramatici de tip 0 (fr restricii) - 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)+

Irina Athanasiu sau de forma


S

3/1/2002

Limbaje formale i automate

n al doilea caz S nu apare n membrul drept al nici unei producii. Se utilizeaz termenul de dependen de context deoarece producia A poate s fie interpretat sub forma - dac simbolul neterminal A apare ntre i atunci 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 ce 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: 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.
2.1.1.1 Exerciii

S se construiasc gramaticile care genereaz limbajul:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

10

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)
2.1.2 Verificarea limbajului generat de ctre o gramatic

n toate exemplele considerate pn acum s-a fcut "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: mulimea reprezentat de limbajul generat de G i mulimea irurilor de paranteze bine formate. Deci demonstraia presupune demonstrarea dublei incluziuni. Adic trebuie s demonstrm c orice ir derivat din S satisface condiia enunat i apoi trebuie s demonstrm incluziunea n sens invers. Dndu-se un ir de paranteze bine nchise trebuie s artm 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

11

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 "adevrat". n general se pot face ns demonstraii "pe poriuni".
2.1.2.1 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.
2.1.3 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 utilizat. 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 fcut substituia simbolilor neterminali. Fiecare nod interior arborelui, reprezint un neterminal. Descendenii unui nod etichetat cu un neterminal A sunt etichetai 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:

Irina Athanasiu

3/1/2002
S //\ \ // \ \ // \ \ (S ) S //\ \ //\ // \ \ (S ) // \ \ | (S ) S | //\ \ // \ \ ( S ) S | |

Limbaje formale i automate

12

\ 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 topdown (descendent). Dar, se poate porni i invers de la irul de atomi lexicali (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 expresiilor 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).
2.1.3.1 Eliminarea ambiguitii

O gramatic care produce mai muli 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

13

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 satisfac o instruciune if. Instruciunea cuprins ntre then i else trebuie s nu fie o instruciune if sau s fie o instruciune 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_cu_else else if_fara_else

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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

14

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 relaiile 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

Fie irul a * a * a. Pentru cele doua gramatici se obin arborii de derivare respectivi:

Irina Athanasiu

3/1/2002
| T /|\ / | \ T * F /|\ | / | \ a T * F | | F a | a

Limbaje formale i automate


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

15

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 nlocuite cu:


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

Producia A' A poate s fie eliminat (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 utilizeaz 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 numete 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 ns o demonstraie, o demonstraie adevrat depete ca dificultate cadrul textului curent.

Irina Athanasiu
2.1.3.2

3/1/2002

Limbaje formale i automate

16

Eliminarea - produciilor

Se spune ca o gramatic este - free dac satisface una dintre urmtoarele condiii: a. Nu exist nici o producie care s aib n partea dreapta irul vid b. Exist o singura producie care are n partea dreapta irul vid i anume o producie de forma S . Simbolul S nu apare n acest caz n partea dreapt a nici unei producii. Algoritmul de transformare pleac de la gramatica G = (N, T, P, S) i construiete 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 P, a N*i-1} Ni-1 pn Ni = Ni-1 Ne = Ni dac S Ne 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 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
2.1.3.3 Eliminarea recursivitii stnga

O gramatic este recursiv stnga dac exist un neterminal A astfel nct exist o derivare A + A pentru (T N)*. O analiz sintactic descendent determinist nu poate s opereze cu o astfel de gramatic, deci este necesar o transformare. S considerm nti cazul cel mai simplu pentru care n gramatic exist producii de forma A A | . n acest caz limbajul generat este de forma n cu n 0. Acelai limbaj poate s fie generat de ctre gramatica: A A', A' A'| .

Irina Athanasiu

3/1/2002

Limbaje formale i automate

17

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 ncepe 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 ncepe 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 este nlocuit de un ir care ncepe cu 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 derivri de tipul A + A (fr cicluri) i nu conine - producii poate s fie transformat n vederea eliminrii recursivitii stnga utiliznd urmtorul algoritm, obinndu-se o gramatic echivalent fr recursivitate stnga.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

18

Se aranjeaz neterminalele n ordinea A1, ..., An pentru i = 1 pn la n executa pentru j = 1 pn la i - 1 executa nlocuiete fiecare producie de forma Ai Aj cu produciile Ai 1 | 2 | ... | k 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' |
2.1.3.4 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 funcioneaz 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 : A A' | A' 1 | 2 | ... | n

Irina Athanasiu

3/1/2002

Limbaje formale i automate

19

A' este un nou neterminal. Se aplic n mod repetat aceast transformare pn cnd nu mai exist dou alternative producii cu un prefix comun pentru acelai simbol neterminal. 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 derivri : S AX BYX aYX ...
2.1.3.5 Eliminarea simbolilor neterminali neutilizai

Un simbol neterminal neutilizat este un simbol care: nu poate s apar ntr-o form propoziional, adic ntr-un ir derivat din simbolul de start al gramaticii (simbol inaccesibil) din care nu poate deriva un ir format numai din simboli terminali (simbol nefinalizabil) care apare n formele propoziionale numai datorit sau mpreun cu simboli neterminali ce satisfac una dintre condiiile anterioare. Pornind de la o gramatic G = (N, T, P, S) se poate obine o gramatic fr simboli nefinalizai i care satisface urmtoarele condiii: (i) L(G) = L(G') (i) A N, A + w, w T*. utiliznd urmtorul algoritm :
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 conine numai produciile 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. Pornind de la o gramatic G = (N, T, P, S) se poate construi o gramatic fr simboli inaccesibili G' = (N', T, P', S) care s satisfac condiiile: (i) L(G) = L(G')

Irina Athanasiu

3/1/2002

Limbaje formale i automate

20

(i) A N', w (N T)*, S w i A apare n w utiliznd urmtorul algoritm.

N0 = {S} i=0 repeta i = i + 1; Ni = {A | A apare n partea dreapta a unei producii pentru un neterminal din Ni-1} Ni-1 pn Ni = Ni-1 N' = Ni P' conine numai producii care corespund neterminalelor din N' si care conin 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 neutilizai. Ordinea n care se aplic aceti algoritmi nu este indiferent. S considerm de exemplu gramatica cu produciile: S a | A, A AB, B b. Dac se aplic nti algoritmul pentru eliminarea simbolilor nefinalizai, rmn produciile S a i B b. Prin eliminarea simbolilor inaccesibili rmne numai producia S a. Dac ns se aplic nti algoritmul pentru eliminarea simbolilor inaccesibili i apoi cel pentru eliminarea simbolilor nefinalizai vor rmne pn la sfrit produciile S a i B b, adic nu se obine o gramatic fr simboli neutilizai. Rezultatul obinut nu este ntmpltor n sensul c nu se poate gsii un exemplu pentru care ordinea corect de aplicare a celor doi algoritmi s fie invers. Ideea este c prin eliminarea unui simbol neterminal neaccesibil nu pot s apar simboli neterminali nefinalizai, n timp ce prin eliminarea unui simbol neterminal nefinalizat pot s apar simboli neterminali inaccesibili deoarece anumii simboli neterminali puteau s fie accesibili numai prin intermediul simbolului neterminal respectiv.
2.1.3.6 Substituia de nceputuri(corner substitution)

Anumite metode de analiz sintactic impun ca partea dreapt a fiecrei producii care nu este irul vid s nceap cu un terminal. S considerm de exemplu gramatica avnd produciile:
lista a(numr) lista | *elem lista | a elem a(numr) | *elem

n acest caz dac pe irul de intrare se gsete terminalul a nu este clar care dintre produciile pentru neterminalul lista trebuie s fie utilizat. Dac factorizm produciile neterminalului lista:
lista aX | *elem lista X (numr) lista | elem a(numr) | *elem

Irina Athanasiu

3/1/2002

Limbaje formale i automate

21

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 ndeplinit 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 excepia 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 poate construi 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:
Se construiete relaia de ordine asupra N astfel nct N= {A1, A2, ..., An} si A1 < A2 < ... < An. pentru i = n - 1 pn la 1 pas = -1 executa fiecare producie de forma Ai Aj cu i < j se nlocuiete cu Ai 1 | ... | m unde Aj 1 | ...| m (se observa ca 1, ..., m ncep cu terminale) pentru fiecare producie de forma p = A a X1 ... Xk execut pentru i = 1 pn la k execut dac Xi T 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:

Irina Athanasiu
' T T' F T ' +TE' FT' *FT' ()

3/1/2002

Limbaje formale i automate

22

| | | | |

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 urmtoarea 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 )

2.1.4

Construcii dependente de context

Anumite construcii specifice limbajelor de programare 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 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 interpretnd gramaticile ca algoritmi de generare de iruri crora le corespund ca echivaleni algoritmi de recunoatere de iruri, se constat c pentru cazul limbajelor regulate este necesar ca pentru recunoatere s se fac o numrare pn la o valoare finit (care poate ns s fie orict de mare). Astfel c limbajul LR = {anbn | 0 n 20000000000000} este un limbaj regulat. Numrul de a-uri ntlnite poate s fie memorat n neterminalele. De altfel, LR este un limbaj finit i deci automat este regulat (produciile gramatici pot s reprezinte de fapt lista irurilor care formeaz limbajul). Limbajul

Irina Athanasiu

3/1/2002

Limbaje formale i automate

23

LR1 = {w {0,1}* | |w| mod 3 = 0} este infinit i regulat. Se observ c pentru recunoaterea irurilor este necesar s se numere cte dou elemente. n schimb limbajul LI = {anbn | 0 n} nu este regulat, algoritmul pe care s-ar baza recunoaterea irurilor nu are o limit. Tratarea unei astfel de situaii se face n mod natural utiliznd un contor infinit sau o stiv.
2.1.4.1 Exerciii

1. Fie gramatica: A BC | a. B CA | Ab, C AB | cC | b S se construiasc 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

24

2.1.5

Proprieti 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 oricror doua limbaje independente de context obinem un limbaj independent de context vom spune c mulimea limbajelor independente de context este nchis sub operaia respectiv. Se poate demonstra c mulimea limbajelor independente de context este nchis sub operaiile: reuniune, concatenare i Kleen 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 S2 * 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 nchis 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 fiind 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, adic 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 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 adevrat. 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, ntr-o manier mai precis dect observaia de la pagina 24. De exemplu s considerm limbajul:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

25

{ an * n | n > 1 } Se pune problema dac exist o gramatica independent de context care s-l genereze. Urmtorul 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. nseamn 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. Dup 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.
2.1.5.1 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
2.2 Mulimi regulate, expresii regulate.

Fie T un alfabet finit. Se numete mulime regulat asupra alfabetului T mulimea construit recursiv n modul urmtor: 1. 2. 3. 4. este o mulime regulat asupra alfabetului T; Dac a T atunci {a} este o mulime regulat asupra alfabetului T; Dac P i Q sunt mulimi regulate atunci PQ, PQ, P* sunt mulimi regulate asupra alfabetului T. 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 mulimilor regulate se poate face cu ajutorul expresiilor regulate. O expresie regulat este la rndul ei definit recursiv n modul urmtor (prin analogie cu definiia mulimilor regulate) :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

26

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 proprieti. Fie , , , expresii regulate. Spunem ca = dac i numai dac i descriu aceleai mulimi regulate. Sunt adevrate urmtoarele proprieti : 1. | = | 2. | ( |) = ( | ) | 3. () = () 4. ( |) = | 5. ( | ) = | 6. ? = ? = 7. * = | * 8. (*)* = * 9. | = 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 + ) Se obine: a*(b + ) = a[a*(b + )] + b = = a+ b + a+ + b = = (a+ + )b + a+ = a*b + a* = a*(b + ) 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 un exemplu de construcie. Fie gramatica G = ({A, B, C}, {0,1}, P,A) cu P = {A 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

Irina Athanasiu C = 0B + 1A +

3/1/2002

Limbaje formale i automate

27

Din prima ecuaie se obine: A = 1*0B. Din a doua ecuaie se obine: B = 0*1C. nlocuind n A se obine: A = 1*00*1C = 1*0+1C. nlocuind 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 sub irul 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: 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|

Irina Athanasiu

3/1/2002

Limbaje formale i automate

28

Rezult gramatica descris de produciile: S 0X | 1S X 0X | 1Y Y 0X | 1S | . Se observ c s-a ajuns la aceeai 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.
2.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 | +-----------+

Banda de intrare este formata din elemente n care se nscriu 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 unitii 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;

Irina Athanasiu coninutul memoriei.

3/1/2002

Limbaje formale i automate

29

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, noiunea 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 acceptat 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 aceeai clas de limbaje. Dintre acestea cele 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.
2.3.1 Automate finite

Un automat finit este un obiect matematic AF = (Q, T, m, s0, F) unde : 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 numete -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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

30

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 eticheteaz 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: 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 -tranziii; 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.
2.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. Se pleac de la o expresie regulat r asupra unui alfabet T i se obine 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

31

1. Pentru expresia , automatul care accept limbajul corespunztor este :


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

2. Pentru expresia a, automatul care accept limbajul corespunztor este :


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

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

32

------------------------| +---+ +-----+ | | | | 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).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

33

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

34

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

2.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 submulimilor 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 -tranziii. 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 : -nchidere i mutare. Funcia -nchidere : 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

35

unde dac s S este o stare care nu are -tranziii atunci: -nchidere({s}) = {s} altfel -nchidere({s}) = -nchidere({s'}) {s} s' m(s,) Construcia funciei -nchidere 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 mutare : 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, mutare(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 execut fie t stari_AFD \ A A = A {t} pentru fiecare a T execut B = -inchidere(mutare(t,a)) stari_AFD = stari_AFD {B} tranz_AFD[t,a] = B

Fie automatul nedeterminist :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

36

---------------+ / | / +-+ +-+ | / | |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(mutare({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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

37

b --\/ +---+ | | b b >| q3|<---------------------+ / +-| | | +---+ /a | +---+ | 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.
2.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:

Irina Athanasiu

3/1/2002
/\ / \ . # /\ / \ 6 . b /\ / \ 5 . b /\ / \ 4 * a | /\ 3 / \ a b 1 2

Limbaje formale i automate

38

Vom ataa fiecrei frunze un cod unic, de exemplu acest cod poate s fie reprezentat de poziia simbolului respectiv n expresia regulat. Fie C mulimea codurilor ataate fiecrei frunze i N mulimea nodurilor arborelui. Fie c funcia de codificare i c-1 funcia invers (c : N C). Definim patru funcii: nullable : N {adevrat, fals} firstpos : N P(C) lastpos : N P(C) followpos : C P(C) 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 adevrat. Funcia firstpos aplicat unui subarbore are ca valoare mulimea 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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

39

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 i i este asociat simbolului x, (i = c-1(x)) atunci followpos(i) este mulimea codurilor j (j = c-1(z)) care satisfac urmtoarea condiie: xy (etichetate cu i i respectiv j ) pot s apar ntr-un ir generat din rdcin. 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 funcia 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 frunz cu eticheta n este o frunz cu eticheta avnd codul i
n | /\ / \ c1 c2 . /\ / \ c1 c2

nullable(n) adevrat fals

firstpos(n) {i}

lastpos(n) {i}

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

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

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

* | c

adevrat

Pentru a calcula followpos(i) care indic ce coduri pot s urmeze dup[ codul i conform arborelui se utilizeaz dou reguli : 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).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

40

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 lastpos sunt reprezentate n stnga 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

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 fiecare nod reprezint un cod iar ntre dou noduri corespunztoare codurilor i i j exist un arc dac j followpos(i).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

41

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

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

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

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

Pe baza unui astfel de graf se poate obine un automat finit nedeterminist fr -tranziii, 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 stri iniiale nu se ncadreaz de fapt n definiia pe care am dat-o pentru un automat finit. Dac ns mai adugm 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

42

stari_AFD = { first_pos(radacina) } // multime de multimi de coduri A= ct timp stari_AFD \ A execut fie t stari_AFD \ A // mulime de coduri A = A {t} pentru fiecare a T execut X = { followpos(p) | c-1(p) = a} pt daca X stari_AFD = stari_AFD {X} tranz_AFD(t,a) = X

n algoritm firstpos(rdcin) este valoarea funciei firstpos aplicat nodului rdcin. Se observ c firstpos(rdcina) corespunde cu -inchidere(s0) iar followpos(p) reprezint nchidere(mutare(...)). 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

43

2.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 ? Algoritmul utilizeaz funciile mutare (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 = mutare(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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

44

2.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 direct pornind de la expresia regulat. n consecin automatul va satisface urmtoarele proprieti: 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. Se consider c exist un mecanism prin care se poate stabilii faptul c s-a ajuns la sfritul irului de intrare (test de tip eof). 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 ajung 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 = -inchidere({s0}) # -inchidere(S) = {s' Q | s S, s' m(s,)} S a = caracterul_urmtor ct timp a eof execut S = -inchidere(mutare(S,a)) # mutare(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 mulimea strilor curente ale automatului, n cealalt mulimea strilor urmtoare. Utiliznd algoritmul de calcul al strilor 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 adugat. 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 proporional cu |N| x |x|. S relum de exemplu automatul :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

45

---------------+ / | / +-+ +-+ | / | |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

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

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

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.
2.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 observ 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 proporional 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 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

46

timp proporional cu |x| indiferent de numrul de stri ale AFD. Aceast abordare este avantajoas dac este necesar verificarea mai multor iruri de lungime mare pentru o aceeai 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 ntreaga tabela de tranziii. 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 nti o cutare n memoria asociativ. Dac nu se gsete se face calculul. 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


2.3.1.7

Minimizarea numrului de stri pentru AFD

Se poate demonstra c fiind dat o mulime regulata exist un unic automat finit determinist cu numr minim de stri 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 adugm 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 stri q1, q2 F exist o secven de intrare care s le separe. Problema construirii automatului redus echivalent unui automat dat este de fapt problema construirii partiiilor induse de o relaie de echivalen. Iniial, considerm ca mulimea Q este mprit 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: Descrierea algoritmului de minimizare este:

Irina Athanasiu
P = {F, Q - F, {d}} repeta P' = P repeta

3/1/2002

Limbaje formale i automate

47

alege A P, Q ne marcat si marcheaz A new = daca |A| > 1 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 new = new {next} se_imparte = true daca new P = P - {A} A = A - new P = P {A}{new} pana nu mai exist A P ne marcat pana P = P'

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

48

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 | +--<--------------------+

Irina Athanasiu

3/1/2002

Limbaje formale i automate

49

2.3.2

Automate cu stiv (pushdown)

Un astfel de automat are o memorie organizat ca o stiv :


+--------------|a0|a1|...|an| banda de intrare +--------------\ cap de citire \ +---------+ | unitate | +----+ | de |---| z1 | | control | |----| +---------+ | z2 | |----| |... | memoria stiva | | |----| | zn | +----+

Un automat cu stiv (PDA) este un obiect matematic 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, ) Q x T* x Z* unde : q - reprezint starea curent a unitii de control; w - reprezint partea din irul de intrare care nu a fost nc citit. Dac w = nseamn c s-a ajuns la sfritul irului de intrare; - 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, 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 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 nlocuiete cu .

Irina Athanasiu

3/1/2002

Limbaje formale i automate

50

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 aib loc i dup ce s-a parcurs ntregul ir de intrare. Dac se ajunge ntr-o configuraie pentru care stiva este goal nu se mai pot executa tranziii. Relaia |- se poate generaliza la |-i, |-+, |-*, ntr-o manier similar relaiei de derivare pentru forme propoziionale. O configuraie iniial pentru un automat cu stiv este o configuraie de forma (q0, w, z0) unde w T*. O configuraie final este o configuraie de forma (q, , ) cu q F, Z*. Aa cum a fost definit automatul cu stiv este nedeterminist, adic pentru o configuraie dat n cazul general pot s urmeze mai multe configuraii urmtoare. Un automat cu stiv este determinist dac pentru orice configuraie exist cel mult o singur tranziie urmtoare. Mai precis un automat cu stiv 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 Spunem c un ir w este acceptat de un automat cu stiv prin stri finale dac este posibil o evoluie ca (q0, w, z0) |-* (q, , ) pentru q F i Z*. Limbajul acceptat de un automat cu stiv P n acest mod se noteaz cu L(P). Se observ c pentru un automat cu stiv nedeterminist pentru un ir dat sunt posibile mai mute evoluii. S considerm de exemplu automatul cu stiv 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)

Irina Athanasiu

3/1/2002

Limbaje formale i automate

51

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 gsete automatul nu este final deci nici acest ir nu este acceptat. Pentru a demonstra c L(P) = {0n1n} trebuie s artm 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 din {0 1 } pentru care n > 0, P trece n mod obligatoriu prin succesiunea de stri q0, q1, q2, q0.
n n

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 = {wcwR| w {a,b}+}, P = ({q0, q1, q2}, {a, b}, {z, a, b}, m,q0, z, {q2}) unde :
m(q0,x,y) m(q0,c,x) m(q1,x,x) m(q1,,z) = = = = {(q0,xy)}, x {a, b}, y {z, a, b} {(q1,x)}, x {z, a, b} {(q1,)}, x {a, b} {(q2,)}

Funcionarea automatului parcurge trei etape. nti se copiaz n stiv irul w, apoi se identific simbolul c care marcheaz mijlocul irului, dup care se descarc stiva conform wR. 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

52

m(q0,x,z) m(q0,x,x) m(q0,a,b) m(q0,b,a) m(q1,x,x) m(q1,b,b)

= = = = = =

{(q0,xz)}, x {a, b} {(q0,xx),(q1,)}, x {a, b} {(q0,ab)} {(q0,ba)} {(q1,)}, x {a, b} {(q1,)}

De data aceasta nu se tie unde se gsete mijlocul irului, astfel nct ori de cte ori simbolul din vrful stivei este acelai cu cel de la intrare s-ar putea s se fi gsit mijlocul irului. Se observ c cel de al doilea automat nu este determinist i c nici nu se poate construi un automat determinist care s accepte limbajul L = {wwR| w {a,b}+}. S considerm de exemplu secvena de micri pentru irul abba.
(q0,abba,z) ||||(q0,bba,az) (q0,ba,baz) (q0,a,bbaz) (q0,,abbaz)

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:
(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.


2.3.2.1 Automate cu stiv cu acceptare prin stiv goal

Fie P = (Q, T, Z, m, q0, z0, F) un automat cu stiv. Spunem c un ir w T* este acceptat de P prin stiva goal dac exist o evoluie pentru care (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 cu stiv 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, )}

Irina Athanasiu Se observ c :

3/1/2002

Limbaje formale i automate

53

(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 cu stiv i limbajul acceptat de acesta prin stiva goal se poate construi un automat cu stiv care accept acelai limbaj prin stri finale.
2.3.2.2 Relaia ntre automate cu stiv i limbajele independente de context

Limbajele acceptate de automatele cu stiv sunt limbajele care pot s fie descrise de gramatici independente de context. Dndu-se o gramatic independent de context s construim automatul care accept limbajul generat de aceasta gramatica. Fie G = (N, T, P, S), se obine automatul cu stiv 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 accept limbajul 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

54

+TT+TF+Ta+Ta+T*F a+F*Fa+a*Fa+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.
/|\ /|\ + T | /|\ | /|\ T T * F | | | | | | F F a | | a a

Acest gen de construire de secvene de derivare i deci automatele cu stiv care accept limbaje prin stiv goal sunt utilizate n analiza sintactic descendent. Un tip special de automat cu stiv l reprezint automatul cu stiv 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 stri finale ( i n acest caz se poate construi un automat echivalent care s fac 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

55

Se poate demonstra c pentru orice automat cu stiv extins , exist un automat cu stiv P astfel nct L() = L(P). S revenim la problema acceptrii limbajelor independente de context de ctre automate cu stiv i s considerm din nou exemplul expresiilor aritmetice. Pentru generarea irului a + a * a putem s considerm i urmtoarea secven de derivri :
+T+T*F+T*a+F*a +a*aT+a*a F+a*aa+a*a

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. Un nceput (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 derivri S Bd aBbbd aabbbbd. Pentru irul obinut abb este nceput deoarece aBbbd este forma 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*aT+a*a F+a*aa+a*a

Rezult arborele de derivare :


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

| | T | | F | | 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 :

Irina Athanasiu

3/1/2002
/|\ /|\ + T | /|\ | /|\ T T * F | | | | | | F F a | | a

Limbaje formale i automate

56

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

Urmtorul nceput este a, etc. Se observ c pentru a identifica un nceput pentru o form propoziional obinut printr-o derivare dreapta se consider secvena frunzelor celui mai din stnga subarbore de adncime 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 reducerea capetelor ("handle pruning"). Dndu-se o gramatic independent de context G = (N, T, P, S) se poate construi un automat cu stiv extins care s opereze conform metodei reducerii capetelor 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 terminalele sunt copiate n stiva; 3. m(q, , $S) = {(r, )}. S construim utiliznd aceast tehnic automatul cu stiv extins care accept limbajul expresiilor aritmetice : R = ({q, r},{a, +, *, (, )},{a, +, *, (, ), T, F, , $}, m, q, $,{r}) unde

Irina Athanasiu

3/1/2002

Limbaje formale i automate

57

m(q, m(q, m(q, m(q, m(q, m(q, m(q, m(q,

b, , , , , , , ,

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

Fiind 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, + a * a, $a) |- (q, + a * a, $F) |- (q, + a * a, $T) |- (q, + a * a, $) |- (q, a * a, $ +) |- (q, * a, $ + a) |- (q, * a, $ + F) |- (q, * a, $ + T) |- (q, a, $ + T *) |- (q, , $ + T * a) |- (q, , $ + T * F) |- (q, , $ + T) |- (q, , $) |- (q, , ?)

Automatele cu stiv construite dup modelul prezentat anterior vor fi utilizate n analiza sintactic de tip ascendent. Avnd n vedere echivalena dintre un automat cu stiv i limbajele independente de context, vom spune c un limbaj independent de context este determinist dac este acceptat de un automat cu stiv determinist. Vom modifica puin condiia de acceptare, considernd c un limbaj independent de context este determinist dac exist un automat cu stiv 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 cu stiv de a recunoate sfritul irului. n acest mod se extinde puin clasa limbajelor independente de context deterministe. Se pune ntrebarea dac orice limbaj independent de context este determinist. S considerm de exemplu limbajul : L = {wwR | w {a, b, c} Dup cum s-a mai discutat un automat cu stiv care accept acest limbaj trebuie s ghiceasc unde este mijlocul irului pentru ca s nceap descrcarea stivei. Intuitiv, o astfel de operaie nu se poate realiza cu un dispozitiv determinist. Propoziie. Exist limbaje independente de context care sunt acceptate de automate cu stiv nedeterministe i nu sunt acceptate de automate cu stiv deterministe.
2.3.3 Maina Turing

Irina Athanasiu

3/1/2002

Limbaje formale i automate

58

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 mrginit 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 limbajului 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. 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; 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 simbolul a sub capul de citire maina trece n starea p. Dac b T atunci simbolul a va fi nlocuit 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

59

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 mainii Turing standard. Fa de aceast definiie exist diferite variante, care permit ca n aceeai micare s se fac i o scriere i o deplasare sau care consider c banda este infinit la ambele capete. Se va arta c toate aceste variante conduc la acceptoare echivalente ca putere. 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, a) (q0, 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 fiind 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 gsete 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, dar nu se oprete (este n stare de agare). 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 (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# # w2 a2 u2# # w1a1 u1 # # w2 a2 u2 # # w1 a1 u1 # # w2 a2 u2 #

Irina Athanasiu

3/1/2002

Limbaje formale i automate

60

dac i numai dac exist b T {L, R} astfel nct m(q1, a1) = (q2, b) i este ndeplinit una dintre urmtoarele condiii: 1. b T, w1 = w2, u1 = u2, a2 = b; 2. b = L, w1 = w2a2 dac a1 # sau u1 u2 = a1 u1 altfel u2 = // capul de citire / scriere este poziionat dup irul de intrare 3. b = R, w2 = w1a1 dac u1 = 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 fiind ntr-o stare de agare (hanging state). Pentru relaia |- se poate considera nchiderea reflexiv i tranzitiv notat cu |-*.
2.3.3.1 Calcule realizate de Maina Turing

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 ntmpltor. 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, a) = (q1, L) m(q0, b) = (q1, L) m(q0, #) = (q1, L) m(q1, a) = (q0, b) m(q1, b) = (q0, a) m(q1, #) = (q2, R) m(q2, a) = (q2, R) m(q2, b) = (q2, R) m(q2, #) = (h, #)

S considerm evoluia pentru irul de intrare aab.

Irina Athanasiu
(q0, #aab#) ||||||||||||-

3/1/2002
(q1, #aab#) (q0, #aaa#) (q1, #aaa#) (q0, #aba#) (q1, #aba#) (q0, #bba#) (q1, #bba#) (q2, #bba#) (q2, #bba#) (q2, #bba#) (q2, #bba#) (h, #bba#)

Limbaje formale i automate

61

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, #II#) |- (q0, #III#) |- (h, #III#). n general :


(q0, #In#) |- (q0, #InI#) |- (h, #In+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 dac w L / dL(w) = \ N 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

62

MT = ({q0, q1, q2, q3, q4, q5, q6}, {a, D, N, #}, m , q0) unde m este o funcie parial definit n modul urmtor :
m(q0, m(q1, m(q1, m(q2, m(q3, m(q3, m(q4, m(q5, m(q5, m(q6, #) a) #) #) a) #) #) D) N) #) = = = = = = = = = = (q1, L) pornim spre stnga (q2, #) se terge un a (q4, R) s-au ters un numr par de a (q3, L) s-a ters un a se continu spre stnga (q0, #) s-au ters doi de a, suntem ca la nceput (q6, R) s-a ajuns la stnga cu un numr imapar de a (q5, D) s-au ters zero sau un numr par de a (h, R) rspuns D i oprire (h, R) rspuns N i oprire (q5, N) au fost un numr impar de a

S considerm evoluia 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, ##) |- (q3, ##) |- (q6, ##) |- (q5, #N#) |- (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 gsete 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 gsete un ir care nu aparine limbajului atunci maina va intra n starea de agare dup ce a ajuns la captul din stnga al benzii.

Irina Athanasiu
2.3.3.2

3/1/2002

Limbaje formale i automate

63

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) configuraii ale acestei 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 ajung 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 aceeai 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 "tie" 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 depi 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 mainile 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 fiind 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 maini 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 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

64

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)

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

Irina Athanasiu
a ---\ / /| \/ / | >R< | b /\ \ | / \ \| ---c

3/1/2002

Limbaje formale i automate

65

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:

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

3/1/2002

Limbaje formale i automate

66

caut mergnd la dreapta un simbol diferit de #, cnd l gsete l copiaz la stnga poziiei pe care la 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 funcioneaz 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#

Irina Athanasiu

3/1/2002

Limbaje formale i automate

67

(q, #abc#) |-* (q, #abc#) |- (q, #abc#) |- (q, ##bc#) L# R # |- (q,##bc#) |- (q,##bc##) R# R# |- (q, ##bc#a#) |- (q, ##bc#a#) |- (q, ##bc#a#) x L# 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#) L# x |- (q, #abc#ab#) |- (q, #ab##ab#) R # |- (q, #ab##ab#) |- (q, #ab##abc#) R#R# x |- (q, #ab##abc#) |- (q,#abc#abc#) L#L# x |- (q, #abc#abc#) |- (q,#abc#abc#) R R# |- (h,#abc#abc#)

n evoluia 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 ... xnxnxn-1 ... xi+1#, i = n-1, ..., 0. Pentru i = 0 se ajunge la #x1 ... xnxn ... x1#.
2.3.3.3 Extensii pentru maina Turing

Avnd n vedere simplitatea deosebit a funcionrii unei maini Turing standard, se pune problema dac aceasta nu poate s fie fcut mai "puternic": prin adugarea unor extensii care s

Irina Athanasiu

3/1/2002

Limbaje formale i automate

68

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. Demonstraiile 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 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 ncepe 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. Demonstraie. 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 | +---------------------------

Irina Athanasiu

3/1/2002

Limbaje formale i automate

69

n simulare se va consider deci c funcionarea maini 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; 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 realizat 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

70

/ (<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


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. trateaz 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 trateaz intrarea n starea de oprire (h) a maini simulate M1. Se observ c la intrarea n aceasta stare se va produce intrarea n starea h i a mainii M1' cu nregistrarea pistei pe care s-a fcut oprirea mainii simulate. Dac banda de intrare a maini 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

71

+------------------------------------------| | 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 definiiei din cazul mainilor Turing standard putem s considerm i n acest caz definiia noiunii 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 decidabilitate referitoare la limbaje pot s fie definite pentru mainile 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 nceputul 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 maini 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})) Dup cum s-a artat pentru orice automat finit nedeterminist se poate construi un automat finit determinist echivalent. n cazul automatelor cu stiv aceasta echivalen nu exist. Cu alte cuvinte automatele cu stiv nedeterministe sunt "mai puternice" dect cele deterministe deoarece automatele cu stiv nedeterministe accepta o clasa mai larga de limbaje. n cazul mainilor 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

72

a, b -\/ b a a b a /| >L -----> L ----> L ----> L ----> L ----> a R | # | | | | | | \| #| b,# | b,# | a,# | b,# | #| -------->------>-------<--------<-------| | /| # | \|

Configuraia din care se pleac este (q, #w#). Maina Turing pornete spre stnga. La un moment dat, la ntlnirea unui simbol b, maina Turing "ghicete" ca a gsit sfritul sub irului cutat. Dac ghicirea este corect atunci maina se va opri, altfel maina nu se oprete. Fiind 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. 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 pstreaz 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 ncercrilor fcute. i anume pe aceast band se gsete 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

73

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 alternativ 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 maini 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 maini 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.
2.3.3.4 Automate liniar mrginite

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 stri 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

74

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).
2.3.3.5 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') M

dac i numai dac


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

Demonstraie. 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']

Irina Athanasiu

3/1/2002

Limbaje formale i automate

75

Demonstraia se realizeaz considernd toate formele posibile de producii. Mai departe 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)

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

76

(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 gramatici 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 ndeplinesc urmtoarea condiie pentru u T1* i v T2* v = f(u) dac i numai dac xuy * x'vy'. n acest caz 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 mainile Turing se pune ntrebarea 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

77

care face parte din L(G) se poate construi o main Turing eventual nedeterminist care s realizeze aceleai operaii.
2.3.3.6 Elemente de calculabilitate

Discuia coninut n acest subcapitol depete cadrul limbajelor formale dar este important pentru a realiza legtura 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 poate s 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 ntrebarea 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). 2.3.3.6.1 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 main 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 ntrebarea dac nu se poate construi o maina Turing care s funcioneze ntr-o manier similar adic, s primeasc 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}:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

78

element | cod(element) ---------+-------------| Ii+1 qi ---------+-------------h |I ---------+-------------L |I ---------+-------------R | II ---------+-------------| Ii+2 ai ------------------------

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 iniiale, 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 satisfac urmtoarele condiii - pentru orice main Turing , M = (Q, T, m, s) :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

79

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)#) 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 maini 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 lsat de U reprezint codificarea rezultatului lsat de M. Pentru a simplifica discuia 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 nscris 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 care s verifice dac irul face parte din limbaj, adic 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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

80

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 /| > M L ----- N | \|

Se observ c M' simuleaz M dup care studiaz rspunsul obinut pe band. Dac rspunsul este N, M' va intra ntr-un ciclu infinit. Se pune ntrebarea 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 enunate 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 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

81

L1 = { w {I,c}* | w nu este codif(M) pentru nici o main Turing sau w = codif(M) pentru o maina 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 ?
. Maina Turing cu limit de timp

2.3.3.7

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 comis-voiajorului. 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 comis-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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

82

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.

d j Dac f(n) = ajn atunci f = O(nd). Adic viteza de cretere polinomial este reprezentat de

Irina Athanasiu j=0

3/1/2002

Limbaje formale i automate

83

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

x t(|w|). Vom spune c limbajul L este acceptabil ntr-un timp t pentru v, u T , a T i 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).

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,

Irina Athanasiu

3/1/2002

Limbaje formale i automate

84

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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

85

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 unui atom lexical recunoscut).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

86

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:

Irina Athanasiu
stare

3/1/2002

Limbaje formale i automate

87

| 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+ ---------------+----------------+--------------------{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} - 3.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 | | | +---------------+

Irina Athanasiu

3/1/2002

Limbaje formale i automate

88

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 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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

89

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. 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.
3.2 Un exemplu elementar de analizor lexical

S considerm analizorul lexical urmatoarea gramatic :


S lista expresie

corespunztor

unui translator pentru limbajul descris de

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

Se observ ca nivelul analizei recunoaterea urmtorilor atomi lexicali :

lexicale

printr-o transformare corespunztoare presupune

Irina Athanasiu
atom lexical numr identificator div mod ( ) * / + ; eof

3/1/2002
actiune

Limbaje formale i automate

90

calcul valoare introduce n tabela de simboli

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

91

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. Aciunile ce trebuie s fie executate n legatur cu execuia analizorului lexical sunt urmtoarele:
A1 : tokenval = NIMIC; return caracter; A2 : b = 0 ;

Irina Athanasiu

3/1/2002

Limbaje formale i automate

92

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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

93

#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 /* 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); 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 */

/* cauta n tabela de simboli */

Irina Athanasiu

3/1/2002

Limbaje formale i automate

94

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; } /* 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");

Irina Athanasiu
}

3/1/2002

Limbaje formale i automate

95

static int lexan() { while(1) { caracter = getchar(); /* A7 */ if (caracter == ' '|| caracter == '\t') ; /* eliminare blancuri si tab-uri */ else if (caracter == '\n') lineno++; else if (isdigit(caracter)) /* caracter este cifra */ { /* 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 litera */ { /* A2 */ b = 0; while (isalnum(caracter)) /* litera sau cifra */ /* A3 */ a3(); /* 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(); } }

Irina Athanasiu

3/1/2002

Limbaje formale i automate

96

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:

Irina Athanasiu
%{ #define #define #define #define #define #define

3/1/2002

Limbaje formale i automate

97

NOTHING -1 NMBER 256 DIV 257 MOD 258 IDENTIFIER 259 FINISH 260

#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; last_character = -1; last_entry = 0; tokenval = NOTHING; lineno = 1; p; /* last character */ /* current token */

Irina Athanasiu

3/1/2002

Limbaje formale i automate

98

len = strlen(s); if (last_entry + 1 >= MAXSYM) error("too many symbols"); 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 [ \t] nl [\n] ws {delim}+ letter [A-Za-z] digit [0-9] letgit [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;

Irina Athanasiu

3/1/2002

Limbaje formale i automate

99

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

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.

Irina Athanasiu

3/1/2002
|2 T /|\3 T * F 4 | /|\ 5 F () 6 | /|\1 a + T |2 |4 T F |4 |6 F a |6 a

Limbaje formale i automate

100

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

Irina Athanasiu
, , , x, ) T) F) x)

3/1/2002
+ T, 1), (q, T, 2)} T * F, 3), (q, F, 4)} (), 5), (q,a,6)} , )} x T

Limbaje formale i automate

101

m(q, m(q, m(q, m(q,

= = = =

{(q, {(q, {(q, {(q,

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


(q, a * (a + a), , ) |- (q, a * |- (q, a * |- (q, a * |- (q, a * |- (q, * |- (q, |- (q, |-+ (q, , (a + a), T, 2) (a + a), T * F, 23) (a + a), F * F, 234) (a + a), a * F, 2346) (a + a), * F, 2346) (a + a), F, 2346) (a + 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:

Irina Athanasiu
(q, a * (a + a), $, ) |||||||||||||||||||-

3/1/2002

Limbaje formale i automate

102

(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. 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).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

103

4.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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

104

4.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 || | | | | |+---+| +---+ +---+ +-----+

':

Irina Athanasiu

3/1/2002

Limbaje formale i automate

105

+---+ +---+ +---+ +-----+ | | + | | 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

Irina Athanasiu
':

3/1/2002

Limbaje formale i automate

106

+---------------+ | | 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 :

Irina Athanasiu
:

3/1/2002

Limbaje formale i automate

107

+ +---------------+ T+|T | | V | +---+ +---+ | | | T | | | | 0 |-----| 3 |---+ | | | | +---+ +---+ +-----+ | |+---+| +----------- || 6 || |+---+| +-----+ * +---------------+ TF*T|F | | V | +---+ +---+ | | | F | | | | 7 |-----| 8 |---+ | | | | +---+ +---+ +------+ | |+----+| +----------- || 13 || |+----+| +------+ F () | a +----+ +----+ +----+ +------+ | | ( | | | | ) |+----+| | 14 |-----| 15 |----| 16 |---|| 17 || | | | | | | |+----+| +----+ +----+ +----+ +------+ | a +-------------------------------+

T:

F:

Analizorul sintactic corespunztor acestor diagrame de tranziie este :

Irina Athanasiu
#include "stdio.h" #include "ctype.h" int caracter_curent; /*

3/1/2002

Limbaje formale i automate

108

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) if (caracter_curent == '+') { gasit('+'); termen(); } else break; } /* T FT', T' *FT' | , T -> T * F | T */ static void termen() { factor(); while (1) if (caracter_curent == '*') { gasit('*'); factor(); } else break; } /*

Irina Athanasiu
F () | a

3/1/2002

Limbaje formale i automate

109

*/

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.
4.1.1.1 Gramatici LL(1)

n cazul analizei LL(1) modelul analizorului este :


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

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

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

stiva

Irina Athanasiu

3/1/2002

Limbaje formale i automate

110

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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

111

initializeaza vrful stivei intitializeaza pozitie curenta pe banda de intrare repeta 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):

Irina Athanasiu

3/1/2002

Limbaje formale i automate

112

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$ | ------------+-----------------------+---------------------'$ | +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) {}

Irina Athanasiu

3/1/2002

Limbaje formale i automate

113

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). 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

114

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:
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).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

115

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).
4.1.1.2 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 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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

116

| 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 |+*)$ | ---------------------------------------------------------------+

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

117

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.
4.1.2 4.1.2.1 Analiza sintactica bottom-up 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.
4.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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

118

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. 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 :

Irina Athanasiu
stiva $ $B $By $A $Az $S

3/1/2002
intrare yz$ yz$ z$ z$ $ se se se se se

Limbaje formale i automate

119

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 ... $

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

120

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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

121

4.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 :

Irina Athanasiu
T T F F +T T T*F F () a

3/1/2002

Limbaje formale i automate

122

(1) (2) (3) (4) (5) (6)

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.

Irina Athanasiu
+------+ +------+ | | a |+----+| | I0 |---|| I5 || | | |+----+| +------+ +------+ +------+ +------+ | | F |+----+| | I0 |---|| I3 || | | |+----+| +------+ +------+

3/1/2002

Limbaje formale i automate

123

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 | | | | | | +------+ +------+ +------+ +------+ +------+ +------+ +------+ | | 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

124

+------+ +------+ | | | | | 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) :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

125

+------+ +------+ +----+ | | + +----+ 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

126

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

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 : dac aciune[sm,ai] = deplasare s, se obine noua configuraie :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

127

(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 :

Irina Athanasiu
T T F F +T T T*F F () a

3/1/2002

Limbaje formale i automate

128

(1) (2) (3) (4) (5) (6)

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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

129

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) ---------------+------------+----------------------------------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). 4.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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

130

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 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).

Irina Athanasiu

3/1/2002

Limbaje formale i automate

131

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)

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:

Irina Athanasiu

3/1/2002

Limbaje formale i automate

132

+----+ +----+ + +----+ 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 :

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

3/1/2002
I1 : ' I2: T I3 : T I4 : F T T F F

Limbaje formale i automate


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

133

T F

.T F

T F

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

134

1. se construieste C = {I0, I1, ..., In} multimea canonic a multimilor de elemente LR(0) pentru G'. 2. starea i este corespunzatoare multimii Ii. Intrarile n tabela actiune pentru starea i se obtin n modul urmator : a) daca [A . a ] Ii si goto(Ii,a) = Ij atunci actiune[i,a] = "deplaseaza j" /* a T */ b) daca [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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

135

(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 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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

136

+------+ +----+ 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. 4.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, s-a 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 aplicat reducerea. Se observ c utilizarea

Irina Athanasiu

3/1/2002

Limbaje formale i automate

137

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

138

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

139

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 :

Irina Athanasiu

3/1/2002

Limbaje formale i automate

140

+----+ 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

141

3. pentru fiecare Ii C si fiecare A N executa daca goto(Ii,A) = Ij atunci goto [i,A] = j 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 :

Irina Athanasiu
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, =/$

3/1/2002

Limbaje formale i automate


I5: L a., =/$ I6: S L = .R, $ R .L, $ 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., $

142

Se observ c pentru I2 se va face reducere dac urmeaz sfritul irului respectiv se va face deplasare dac urmeaz =. 4.1.2.3.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

Irina Athanasiu

3/1/2002

Limbaje formale i automate

143

reflecta noile mulimi ntre care se fac tranziii iar n tabela actiune se nlocuiesc o serie de intrri de eroare cu intrri de reducere. 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.

Irina Athanasiu

3/1/2002

Limbaje formale i automate

144

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, PrenticeHall 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

You might also like