P. 1
Irina Athanasiu Limbaje Formale Si are Curs

Irina Athanasiu Limbaje Formale Si are Curs

|Views: 59|Likes:
Published by ggardu

More info:

Published by: ggardu on Mar 25, 2012
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

03/25/2012

pdf

text

original

Institutul Politehnic Bucuresti Catedra de calculatoare

conf. dr. ing. Irina Athanasiu

LIMBAJE FORMALE SI TRANSLATOARE (note de curs)

- 1991-

Introducere - organizarea unui compilator . . . . . . . . . . 1 1. Elemente de teoria limbajelor formale . . . . . . . . . . 5

1.1. Gramatici . . . . . . . . . . . . . . . . . . . . . . 6 1.1.1. Verificarea limbajului generat de catre o . . . 8

gramatica 1.1.2. Transformari asupra gramaticilor . . . . . . . 9 1.1.3. Constructii dependente de context . . . . . . . 22 1.1.4. Propietati ale limbajelor independente de . . . 23 context 1.2. Multimi regulate, expresii regulate. . . . . . . . . . 25 1.3. Acceptoare . . . . . . . . . . . . . . . . . . . . . . 1.3.1. Automate finite . . . . . . . . . . . . . . . . 1.3.1.1. Constructia unui automat finit nedeterminist care accepta limbajul descris de o expresie regulata data 1.3.1.2. Conversia unui automat finit nedeterminist (AFN) intr-un automat finit determinist(AFD) 1.3.1.3. Constructia unui automat finit determinist care accepta limbajul descris de o expresie regulata data 1.3.1.4. Simularea unui automat finit determinist 1.3.1.5. Simularea unui automat finit nedeterminist 1.3.1.6. Probleme de implementare pentru automatele finite deterministe si nedeterministe 1.3.1.7. Minimizarea numarului de stari pentru AFD 28 30 31 34 38 43 44 46 48

1.4. Automate cu stiva(pushdown) . . . . . . . . . . . . . 50 1.5. Masina 1.5.1. 1.5.2. 1.5.3. 1.5.4. Turing . . . . . . . . . . . Compunerea masinilor Turing. . Extensii pentru masini Turing Relatia intre masina Turing si Elemente de calculabilitate . . . . . . . . . . . . . . . . gramatici . . . . . . . . . . . . . . . . . . . . 60 65 70 77 80

2. Analiza lexicala . . . . . . . . . . . . . . . . . . . . . 86 2.1. Interfata analizorului lexical . . . . . . . . . . . 89 2.2. Aspecte privind implementarea unui analizor lexical 92 2.3. Un exemplu elementar de analizor lexical . . . 3. Analiza sintactica . . . . . . . . . . . . . . . . . 3.1. Analiza sintactica top - down . . . . . . . . 3.1.1. Analiza sintactica predictiva . . . . . (descendent recursiva) 3.1.2. Gramatici LL(1) . . . . . . . . . . . . 3.1.3. Tratarea erorilor in analiza predictiva 3.2. Analiza sintactica bottom-up . . . . . . . . . 3.2.1. Analiza sintactica de tip . . . . . . . deplaseaza reduce 3.2.2. Implementarea analizei sintactice . . . bottom-up deplaseaza reduce 3.2.3. Gramatici de precedenta cu operatori . . 3.2.4. Relatii de precedenta stabilite pe baza proprietatilor de asociativitate si prioritatile operatorilor 3.2.5. Analiza sintactica de tip LR(k) . . . . . . . . . . . . . . . . . . . . . 94 102 105 106 112 117 119 119

. . 119 . . 122 . . 125 . . 129

3.2.5.1. 3.2.5.2. 3.2.5.3. 3.2.5.4. 3.2.5.5. 3.2.5.6.

Analiza SLR . . . . . . . . . . Analiza canonica LR . . . . . . Analiza sintactica LALR . . . . Compactarea tabelelor LR . . . Utilizarea gramaticilor ambigue Revenirea din eroare pentru . . analiza LR

. . . . . .

. . . . . .

137 143 148 156 158 164

Bibliografie . . . . . . . . . . . . . . . . . . . . . . . 167 Introducere - organizarea unui compilator Un compilator este un program complex care realizeaza traducerea unui program sursa intr-un program obiect. De obicei programul sursa este scris intr-un limbaj de nivel superior celui in care este scris programul obiect. Structura generala pentru un compilator este: program sursa +-----------------+ preprocesor +-----------------+ + - - - - - - -

pas 1

pas 2 - - - - - - - - - - - - - - - - - - - - - - +

+------------------+ +--------------------+ analiza lexicala ---------> analiza sintactica <--------+------------------+ +--------------------+ +------------------+ +--------------------+ gestiunea tabelei analiza semantica de simboli <--------+------------------+ +--------------------+ +--------------------+ generarea de cod intermediar +--------------------+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ cod intermediar +-------------------pas 3 +--------------------+ optimizare +--------------------+ cod intermediar +--------------------+ generarea de cod +--------------------+ limbaj de asamblare sau cod masina Preprocesorul realizeaza activitati de tip macro substitutie,

pas 4

analiza semantica. >. while. In primul caz generarea de cod poate sa fie mai simpla. Al doilea pas reprezinta de fapt componenta principala a unui compilator (celelalte componente ar putea sa lipseasca). In general. Pe de alta parte existenta unui numar mare de atomi lexicali poate complica in mod exagerat analiza sintactica. un cuvint cheie al limbajului (for. Pasul cel mai complex dintr-un compilator ramine pasul 2 in care se realizeaza cele mai importante operatii fara de care nu poate avea loc procesul de compilare. Un analizor lexical apare in general ca o procedura care interfera cu restul compilatorului printr-o interfata simpla : ori de cite ori analizorul sintactic are nevoie de un nou atom lexical va apela analizorul lexical care ii va intoarce atomul lexical urmator. Analiza sintactica . Analiza lexicala Aceasta faza a compilatorului realizeaza traducerea textului programului intr-o forma mai usor de prelucrat de catre celelalte componente. Una dintre decizile ce trebuie luate la inceputul proiectarii unui compilator consta din stabilirea atomilor lexicali. cit si informatii privind tipul numarului sau valoarea acestuia. Pentru un numar este semnificativa atit clasa. Adica. Un atom lexical poate sa fie de exemplu. se pune problema daca sa existe cite un atom lexical pentru fiecare operator de comparatie (<. Se observa ca nu exista o corespondenta biunivoca intre sirurile de intrare si atomii lexicali. Sirul de intrare initial pe care analizorul lexical il recunoaste ca atom lexical este numit in literatura de specialitate "lexema". daca pentru atomul lexical corespunzator cuvintului cheie while exista un singur sir de intrare. Prima informatie este necesara pentru analiza sintactica in timp ce a doua informatie este semnificativa pentru generarea de cod. operatorii care au aceasi prioritate si asociativitate pot sa fie grupati impreuna. Si anume. Efectul executiei acestui pas consta din verificarea corectitudinii formale a textului programului si traducerea acestui text intr-o forma intermediara. gestiunea tabelei de simboli si generarea de cod nu sint neaparat identificabile sub forma unor proceduri ori functii distincte. Un atom lexical este reprezentat printr-un cod numeric care specifica clasa acestuia si o serie de atribute care pot sa fie specifice fiecarei clase. analiza sintactica. Astfel. etc.eliminarea comentarilor. analizorul lexical considera textul primit la intrare ca fiind format din unitati lexicale pe care le recunoaste producind atomi lexicali. In cele ce urmeaza aceste componente vor fi descrise separat pentru simplificarea expunerii. Rolul unui analizor lexical este de a traduce sirurile de intrare in atomi lexicali. Intr-un compilator real cele cinci componente care il formeaza : analiza lexicala. etc) dar si un numar sau un nume. >=) sau sa existe un unic atom lexical corespunzator operatiei de comparatie. pentru atomul lexical corespunzator unui numar intreg pot sa existe foarte multe siruri de intrare. poate sa existe clasa operatorilor relationali pentru care trebuie sa se specifice si tipul concret al operatorului. De exemplu. Ultimii doi pasi realizeaza prelucrari asupra programului in cod intermediar in scopul imbunatatirii performantelor acestuia (optimizarea) si generarii programului obiect. <=.

Analiza semantica Aceasta faza poate sa fie practic incorporata in faza de analiza sintactica. Sa consideram de exemplu expresia : A * B + C * D Aceasta expresie poate sa fie descrisa de urmatorul arbore (numit arbore sintactic) : + / / / * / / A \ \ B C / / \ \ \ * \ \ D In acest arbore au fost evidentiate relatiile (din puctul de vedere al modului de evaluare) intre componentele expresiei.Analiza sintactica descompune textul programului sursa in componentele sale "gramaticale". Un analizor sintactic poate sa construiasca efectiv o structura de date de tip arbore (cu pointeri si inregistrari) sau poate sa sintetizeze informatiile din care se poate face constructia acestuia. Majoritatea verificarilor realizate de catre aceasta faza se refera la tipurile elementelor. structura arborelui devine : expresie factor + factor / / / factor * factor nume A nume B \ \ \ factor * factor nume C nume D Arborele astfel obtinut se numeste arborele de derivare (parse tree). De asemenea aceasta faza completeaza arborele de derivare cu o serie de informatii necesare generarii de cod. Daca se doreste insa sa se evidentieze structura expresiei din punctul de vedere al unitatiilor sintactice din care este formata. construind un arbore care reflecta aceasta structura. Orice analizor sintactic realizeaza de fapt traducerea unui sir de atomi lexicali intr-un astfel de arbore de derivare care descrie de fapt relatia ierarhica intre o descriere generala a propozitiei analizate (radacina arborelui) si sirul de atomi lexicali din care este format (frunzele). Rolul acestei faze consta din verificarea din punct de vedere semantic a structurilor recunoscute drept corecte din punct de vedere sintactic. Generarea de cod .

De exemplu daca la nivelul sintaxei poate sa apara ca fiind corecta o expresie de forma: nume + nume. Fiecare atom in parte este corect dar nu formeaza impreuna o propozitie corecta din punct de vedere sintactic.Aceasta faza nu este intodeauna separata de analiza sintactica. In general o tabela de simboli este o structura de date care contine cite o inregistrare pentru fiecare identificator avind cimpuri pentru atributele posibile. In primul rind anumite optimizari nu se pot face in timpul analizei sintactice si sint dificil de realizat pe un text de program intr-un limbaj de programare de nivel foarte scazut. atunci este rolul analizei semantice sa identifice ca eronata o expresie in care primul nume este al unui vector iar al doilea nume este al unei proceduri. Alt motiv ar putea sa fie utilizarea aceleeasi faze de optimizare si generare de cod masina pentru diferite limbaje de programare. in analiza lexicala intilnirea unui sir care nu corespunde unui atom lexical. Detectarea erorilor Fiecare faza a unui compilator poate sa identifice prezenta unei erori specifice. exista compilatoare care genereaza cod chiar in timpul analizei sintactice. In faza de analiza semantica se verifica daca constructiile corecte din punct de vedere sintactic sint corecte si din punct de vedere semantic. Utilizarea formelor intermediare se justifica prin citeva argumente. Atributele acestora sint completate in tabela de catre analizoarele sintactic si semantic. pentru ca un compilator care se opreste la prima eroare . Introducerea simbolilor in tabela se face in general de catre analizorul lexical. Dezavantajul utilizarii unei forme intermediare consta in mod evident din marirea timpului necesar pentru executia unei compilari. De asemenea o astfel de faza poate sa fie utilizata pentru realizarea de compilatoare incrementale sau interpretoare. Aceste informatii pot sa se refere la tip. Ceea ce se genereaza de obicei este o forma intermediara din care eventual se poate reconstitui arborele de derivare de catre pasul de optimizare. domeniu de valabilitate. deoarece este mai simplu de realizat optimizarea pe un arbore decit pe o structura liniara. Ca de exemplu: int real alfa. fara nici o restrictie asupra tipului identificatorilor corespunzatori. daca este vorba de identificatori de tip nume de procedura la aceste informatii se adauga si numarul si tipul argumentelor eventual modul de transfer al parametrilor. Gestiunea tabelei de simboli In tabela de simboli se inregistreaza identificatorii utilizati in program si informatii asupra acestora.editare de legaturi. Problema cea mai dificila legata de tratarea erorilor consta din modul in care se continua analiza dupa identificarea unei erori. Acest tip de translatoare executa direct codul intermediar fara a mai trece prin fazele urmatoare . incarcare. In general generarea de cod se face prin parcurgerea arborelui de derivare. in analiza sintactica se identifica erori legate de structura instructiunilor. De exemplu. etc.

Se poate demonstra ca multimea A* este infinit numarabila (se poate construi o bijectie f : N --> A*). . Exceptie face modul de abordare in primele versiuni ale compilatorului pentru TURBO Pascal pentru care la intilnirea unei erori se revine in regim de editare pentru corectarea acesteia. S) unde : . Din acest motiv nu orice limbaj va putea sa fie reprezentabil intr-un mod finit. Sa consideram de exemplu limbajul "sirurilor formate din 0 si 1 a caror lungime este divizibila cu 3". Numarul de limbaje ce se pot construi utilizind simboli dintr-un * alfabet dat T. cazul interesant este insa cel in care limbajul este infinit. P.P este o submultime finita din (N U T)* N (N U T)* x (N U T)*.1. nu sintem interesati chiar de orice limbaj. Spre norocul nostru. In al doilea caz este vorba de un "dispozitiv" care stie sa recunoasca (sa accepte ca fiind corecte) propozitiile limbajului dat. Elemente de teoria limbajelor formale Fie T o multime de simboli denumita alfabet.S E N este un simbol special numit simbol de start al gramaticii G. Deci exista o multime infinit numarabila de reprezentari finite.N este o multime finita de simboli numita multimea simbolilor neterminali. 1.1}* w mod 3 = 0} Se pune problema daca dindu-se un limbaj oarecare este posibila construirea unei reprezentari finite. T.intilnita nu este prea comod de utilizat. . . este 2T deci este infinit nenumarabila. In general exista doua mecanisme distincte de definire finita a limbajelor : prin generare sau prin recunoastere. Daca limbajul este finit atunci el poate sa fie definit prin enumerare. Gramatici O gramatica reprezinta cel mai important exemplu de generator de limbaje. Evident este vorba de un limbaj infinit. Elementele limbajului se numesc propozitii. Prin definitie o gramatica este G = (N. 1. Sa consideram ca o astfel de reprezentare finita se realizeaza utilizind simboli dintr-un alfabet finit A.T este o multime finita de simboli numita multimea simbolilor terminali (T n N = O). Rezulta deci ca ar trebui sa reprezentam un numar infinit nenumarabil de obiecte utilizind un numar infinit numarabil de reprezentari. Nu este singura solutie posibila. Textul pe care l-am dat pentru a specifica limbajul constituie o reprezentare finita a limbajului. . Orice submultime a multimii T* reprezinta un limbaj asupra alfabetului T. De exemplu daca notam cu L limbajul respectiv atunci L = { w E {0. In primul caz este vorba de un "dispozitiv" care stie sa genereze toate propozitiile din limbaj (si numai pe acestea) astfel incit alegind o propozitie din limbaj intr-un interval finit de timp dispozitivul va ajunge sa genereze propozitia respectiva.

.literele mici de la inceputul alfabetului latin (a. 000111 este o propozitie in L(G). . . w E T+... .literele mici de la sfirsitul alfabetului latin (u.b. 0A -> 00A1.ak forme propozitionale astfel incit a = a0. S) unde P = {S-> 0A1. ... p = (a. O forma propozitionala pentru o gramatica G se defineste recursiv in modul urmator : (1) S este o forma propozitionala (2) daca aBt este o forma propozitionala si exista o productie B -> r atunci art este o forma propozitionala.... Conform observatiei facute la inceputul acestui capitol nu orice limbaj are o reprezentare finita. Se observa ca o gramatica este o reprezentare finita (toate elementele sale sint finite) a unui limbaj care poate sa fie infinit. Si anume : . C. w2 si z -> s E P astfel incit a = w1 z w2 si B = w1 s w2. Inchiderea tranzitiva a relatiei =G> se noteaza cu =+>. S =+> 0A1 =*> 0A1.. In cele ce urmeaza vom utiliza o serie de notatii devenite de fapt "clasice". . Inchiderea tranzitiva si reflexiva a relatiei =G> se noteaza cu =*>. X. . Relatia =G> poate sa fie extinsa obtinindu-se derivarea in k pasi. . S =+> w}. V.) reprezinta siruri din (N U T)* (siruri de simboli terminali si neterminali).. cu alte cuvinte nu pentru orice limbaj exista o gramatica care sa il reprezinte. Si anume a =k> B daca exista a0.literele mari de la sfirsitul alfabetului latin (U.) reprezinta elemente din T* (siruri de simboli terminali). Fie a si B doua forme propozitionale. Asupra formelor propozitionale se defineste o relatie numita relatie de derivare =G> in modul urmator. Notam cu L(G) multimea tuturor propozitiilor generate de G.. Doua gramatici G si G' sint echivalente daca si numai daca L(G) = L(G'). a =G> B daca si numai daca exista w1.. S =G> 0A1 =G> 00A11 =G> 000A111. B) este notat cu a -> B si se numeste productie.) reprezinta elemente din N U T (simboli terminali sau neterminali).... a1.) reprezinta elemente din T (simboli terminali). B. O forma propozitionala care contine numai simboli terminali se numeste propozitie generata de G.c. Sa consideram de exemplu gramatica G = ({A. B.. L(G) este limbajul generat de gramatica G.literele mari de la inceputul alfabetului latin (A.) reprezinta elemente din N (simboli neterminali).Un element p E P. {0. P. A -> ?} (cu ? s-a notat sirul vid de simboli). Se observa ca L(G) = { w Ierarhia Chomsky.literele alfabetului grecesc (a. v.1}.S}. ai-1 =G> ai 1 <= i <= k si ak = B.. x.

Gramaticile pot sa fie clasificate conform complexitatii productilor in urmatoarea ierarhie : gramatici de tip 0 .{S -> AS. S).au productiile de forma a -> B cu a E (N U T)* N (N U T)* . A -> ?. Se poate arata simplu ca intre gramaticile care formeaza ierarhia exista o relatie de incluziune. Rezulta deci ca un acelasi limbaj poate sa fie definit de mai multe gramatici diferite eventual chiar de tipuri diferite (evident orice gramatica regulata este si o gramatica independenta de context. etc.{0. T. r E (N U T)+ (se observa ca aAB < arB ). E -> T. S -> ?}. a E (N U T)*. E) cu P = { E -> E + T. Adica orice gramatica regulata este o gramatica independenta de context.{S -> 0S. Sa considerm un exemplu de derivare in aceasta gramatica : E => E + T => T + T => F + T => a + T => a + T * F => a + F * F => a + a * F => a + a * a.au productiile de forma : a A B -> a r B. gramatici de tip 2 (independente de context) productiile de forma : A -> a. si o gramatica dependenta de context. F -> a}. P. A E N. A E N. c) G3 = ({E. A -> 1}. In cele ce urmeaza pentru simplificarea notatiilor daca pentru un neterminal exista mai multe productii : de au . T -> T * F.1}. B E (N U T)* gramatici de tip 1 (dependente de context) .1}.1}*. In cazul garamaticilor de tip 1. *. Se observa ca G2 este o gramatica independenta de context iar limbajul generat este tot {0. S).{0. A -> 0. orice gramatica independenta de context este o gramatica dependenta de context. a. Se observa ca G1 este o gramatica regulata care genereaza limbajul {0. gramatici de tip 3 (regulate la dreapta) au productii forma: A -> aB cu A E N . S -> ?. T -> F. +. Se observa ca gramatica G3 este o gramatica independenta de context si este o gramatica care descrie limbajul expresiilor aritmetice cu paranteze care se pot forma cu operandul a si cu operatorii + si *.1}*. exista eventual si o productie S -> ? in acest caz S nu apare in membrul drept al niciunei productii. etc). B E (N U T)*. )}. (. A}.{a. Sa consideram citeva exemple: a) G1 = ({S}. F -> (E). b) G2 = ({S. S -> 1S. F}. B E (N U {?}) si a E T*.

. Sirul vid care se obtine intr-un pas din S este un sir de paranteze bine inchise.1. In acest caz x si y pot sa fie derivate din S. S) Aceasta gramatica genereaza toate sirurile de paranteze bine inchise (echilibrate). Se pune insa problema cum se poate demonstra corectitudinea rezultatului unei astfel de ghiciri. Sigur sirul incepe cu o paranteza deschisa. Sa consideram de exemplu gramatica: G = ({S}. Se observa ca w = (x)y. Adica. Desigur o astfel de demonstratie este practic imposibil de realizat pentru un limbaj "adevarat". A -> wk vom reprezenta aceste notatii sub o forma mai compacta : A -> w1 w2 . De asemenea pentru specificarea unei gramatici nu vom mai preciza in general decit multimea productiilor sale. . Insa in general se pot face pe portiuni demonstratii ca cea de mai sus. dindu-se un sir de paranteze bine inchise trebuie sa aratam ca acest sir poate sa fie derivat din S.)}. Rezulta ca exista o derivare: S ==> (S)S =*=> (x)y in care pentru obtinerea sirurilor x si respectiv y s-au utilizat mai putin de 2n pasi si deci w este un sir derivabil din S. O astfel de derivare poate sa arate ca : S ==> (S)S =*=> (x)S =*=> (x)y unde x si y sint siruri de terminale derivate din S in mai putin de n pasi. Cu alte cuvinte orice sir derivat din S este "corect". Fie (x) cel mai scurt prefix format din paranteze bine inchise.. Dorim insa sa demonstram aceasta afirmatie. A -> w2. In acest scop trebuie sa demonstram ca orice sir derivat din S satisface conditia enuntata si apoi trebuie sa demonstram incluziunea in sens invers. Sa consideram acum si demonstratia in sens invers. . {S --> (S)S ?}. wk. Sa presupunem acum ca orice sir cu mai putin de 2n simboli este derivabil din S.1. Pentru prima parte a demonstratiei vom utiliza inductia asupra numarului de pasi in derivare. De data asta demonstratia se face prin inductie asupra lungimii sirului. cu n mai mare sau egal cu 1.. {(. Pentru primul pas observam ca sirul vid este un sir derivabil din S. Rezulta deci ca sirul (x)y este un sir de paranteze bine inchise. unde x si y sint siruri de paranteze bine inchise de lungime mai mica decit 2n. Sa consideram un sir w de paranteze bine inchise avind lungimea de 2n. celelalte elemente rezultind in mod banal din aceasta. 1. Sa presupunem ca pentru toate derivarile realizate in mai putin de n pasi se obtin siruri de paranteze bine inchise si sa consideram o derivare de exact n pasi.. Verificarea limbajului generat de catre o gramatica In toate exemplele considerate pina acum s-a facut "ghicirea" gramaticii care genereaza un limbaj dat sau a limbajului generat de catre o gramatica data.A -> w1.

1. Descendentii unui nod etichetat cu un neterminal A sint etichetati de la stinga la dreapta prin simbolii care formeaza partea dreapta a unei productii care are in partea stinga neterminalul A. pentru care se utilizeaza gramatici independente de context. Transformari asupra gramaticilor Utilizarea unei gramatici este interesanta pentru faza de analiza sintactica. Exista o serie de metode de analiza sintactica.1. Deoarece analiza sintactica se realizeaza pe baza arborelui de derivare vom prezenta in continuare citeva informatii legate de acesta.)}. Intr-un arbore de derivare nu se mai poate identifica ordinea in care s-a facut substitutia simbolilor neterminali. In cele ce urmeaza vom prezenta citeva transformari tipice asupra gramaticilor independente de context. {(.2. {S --> (S)S ?}. transformari care pastreaza neschimbat limbajul generat. bine puse la punct atit din punct de vedere teoretic cit si practic. In general atunci cind se construieste o gramatica se pleaca de la forma generala a structurilor pe care aceasta trebuie sa le descrie si nu de la metoda de analiza sintactica ce va fi utilizata. S) Sa consideram de exemplu urmatoarea secventa de derivari: S ==> ( S ) S ==> ( ( S ) S ) S ==> ( () S ) S ==> ( () ( S ) S ) S ==> ( () () S ) S ==> ( () () ) S ==> ( () () ) ( S ) S =+=> ( ()() ) () Se obtine arborele de derivare: S / / \ \ / / \ \ / / \ \ ( S ) S / / \ \ / / \ \ / / \ \ ( S ) S / / \ \ ( S ) S ? ? ? / / \ \ / / \ \ ( S ) S . Un arbore de derivare este o reprezentare grafica pentru o secventa de derivari. Pentru a satisface insa conditiile impuse de catre metodele de analiza sintactica sau de catre generarea de cod. se realizeaza transformari asupra gramaticilor. Sa consideram de exemplu din nou gramatica sirurilor de paranteze bine formate: G = ({S}. In acest mod se obtine o gramatica ce poate sa fie "citita" si deci verificata. Fiecare dintre aceste metode impune insa o serie de restrictii asupra gramaticilor utilizate. Parcurgind de la stinga la dreapta frunzele unui astfel de arbore se obtine o forma propozitionala. reprezinta un neterminal. Fiecare nod interior arborelui.

Dar. Eliminarea ambiguitatii O gramatica care produce mai multi arbori de derivare pentru aceeasi propozitie este o gramatica ambigua. Deoarece exista tehnici de analiza sintactica care lucreaza numai cu gramatici neambigue vom incerca sa construim gramatici care genereaza acelasi limbaj si care sint neambigue. considerind de exemplu gramatica expresilor aritmetice pentru sirul a + a * a se obtine arborele derivare : E / \ / \ E + T / \ T / \ T * F F F a a a in care se poate observa ca a fost evidentiat faptul ca operatia de inmultire este prioritara fata de operatia de adunare (aspect semantic). Deoarece arborele de derivare descrie relatia ierarhica intre entitatile sintactice (neterminale) si atomii lexicali (terminale) se poate asocia o interpretare in termeni de evaluare a entitatilor sintactice. Astfel. In acest caz se spune ca analiza sintactica este de tip bottom-up. se poate porni si invers de la sirul de atomi lexicali (frunze) identificindu-se simbolii neterminali din care se poate obtine un sir de atomi lexicali. a. Sa consideram de exemplu urmatoarea gramatica : instr -> if expresie then instr if expresie then instr else instr alte_instr Sa construim arborele de derivare pentru propozitia : if E1 then if E2 then S1 else S2 instr / /\ \ / / \ \ / / \ \ / expr \ \ / / \ then \ if / E1 \ \ ------instr / /\ \ \ \ / / \ \ \ \ / / \ \ \ \ / expr \ \ \ \ / / \ then \ \ \ .? ? Arborele de derivare este construit de catre analizorul sintactic.in acest caz se spune ca analiza sintactica este top-down. Aceasta constructie se poate face pornind de la radacina aplicind succesiv productii .

Instructiunea cuprinsa intre then si else trebuie sa nu fie o instructiune if sau sa fie o intructiune if cu clauza else. Rezulta deci conditia pe care trebuie sa o satisfaca o instructiune if.-----In toate limbajele de programare care accepta constructii de tip if then else se considera cu sens prima derivare in care fiecare clauza else este atribuita instructiunii if cea mai interioara.if / E2 \ ------- \ \ \ instr \ \ / \ else \ / S1 \ instr -----/ \ / S2 \ ------ Pentru aceasta propozitie mai exista insa un arbore de derivare : instr / / \ \ \ \ / / \ \ \ \ / / \ \ \ \ / expr \ \ \ \ / / \ then \else \ if / E1 \ \ \ ------instr instr / \ / \ / /\ \ / S2 \ / / \ \ -----if / then\ expr instr / \ / \ / E2 \ / S1 \ -----. Rezulta urmatoarea gramatica obtinuta 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 observa ca aceasta gramatica genereaza acelasi limbaj cu gramatica anterioara dar accepta o derivare unica pentru propozitia : if E1 then if E2 then S1 else S2 instr if_fara_else / /\ \ / / \ \ / / \ \ / expr \ \ / / \ then \ if / E1 \ \ ------instr if_cu_else / /\ \ \ \ .

E --> T + E T --> F * T F --> a T F T F Sa consideram sirul a * a * a. Sa consideram gramatica G = ({S. A -> a b}). E --> E + T T --> T * F F --> a 2. Se observa ca aceasta gramatica nu este ambigua. {a. {S -> aAbAc. Existenta unei productii ambigue nu implica faptul ca gramatica este ambigua. +. Pentru cele doua gramatici se obtin arborii de derivare respectivi: E E T / / T / / T * \ \ a F a * \ \ F F / / T \ \ * / / F * T \ \ T . b. c }. {E -> E + E E * E a}./ / \ \ \ \ / / \ \ \ \ / expr \ \ \ \ / / \ then \ \ \ if / E1 \ \ \ \ ------instr \ \ / \ else \ / S1 \ instr -----/ \ / S2 \ -----Se numeste productie ambigua o productie care are in partea dreapta mai multe aparitii ale aceluiasi simbol neterminal. E) Gramatica G este o gramatica ambigua (se poate verifica usor utilizind sirul a + a * a). *}. {a. A}. Sa consideram de exemplu si gramatica pentru expresii aritmetice: G = ({E}. Aceasta gramatica poate sa fie transformata intr-o gramatica neambigua in doua forme: 1.

Simbolul S nu apare in acest caz in partea dreapta a nici unei productii. an. an E T* acestea pot sa fie inlocuite cu: A --> A' B A A' --> A a1 A' a2 . P..productiilor Se spune ca o gramatica este ?... De exemplu limbajul : L = { aibjckdl este inerent ambiguu. Trebuie sa remarcam insa faptul ca exista limbaje pentru care nu se pot construi gramatici neambigue.. .. S') care satisface conditiile : (i) L(G) = L(G') i = k sau j = l. an . Un astfel de limbaj se numeste inerent ambiguu. In cazul general daca pentru un neterminal A exista productiile: A --> A B A a1 a2 . Exista o singura productie care are in partea dreapta sirul vid si anume productia S --> ?. k.. i. T.free daca satisface una dintre urmatoarele conditii : a. Eliminarea ? . j.F a a F a a Se observa ca primul arbore evidentiaza asociativitatea stinga a operatorului * in timp ce al doilea arbore evidentiaza asociativitatea dreapta. In functie de definitia limbajului si de modul in care arborele de derivare va fi explorat pentru generarea de cod este de preferat prima sau a doua solutie. B. an Productia A' --> A poate sa fie eliminata (exista si A --> A') si se obtine: A --> A' B A A' --> a1 a2 A' .. b. Pentru a se obtine asociativitate stinga se utilizeaza transformarea: A --> A B A' A' --> a1 a2 A' . P'. S) Iesire O gramatica G' = (N'. Nu exista nici o productie care sa aiba in partea dreapta sirul vid sau b. T. a1.. Algoritmul de transformare este : Intrare O gramatica G = (N. l >= 0} . an Daca se construieste arborele de derivare se observa ca in acest caz se utilizeaza asociativitatea dreapta...

examinind numai primul simbol terminal(a) nu este clar cu care dintre productiile pentru E trebuie sa se inceapa derivarea. k >= 0. 1 <= i <= k.. In acest caz se poate face transformarea : A --> r A'. T -->FT'.. E' --> +TE' F --> (E) a ?.. Sa consideram de exemplu gramatica expresiilor aritmetice : E --> E + T T.(ii) G' este ? . Bk ak. A' --> BA' ?. ?}} \ {A --> ?}) altfel P' = P' U {p} = = Fie de exemplu gramatica S --> aSbS algoritmul anterior se obtine : S' --> S. Aplicind bSa baS ba c. Sa consideram intii ca in gramatica exista productiile A --> AB r. S --> aSbS aSb abS ab bSaS bSaS ?. T --> T * F F. Aplicind ideea anterioara se obtine : E --> T E'. Eliminarea recursivitatii stinga O gramatica este recursiva stinga daca exista un neterminal A astfel incit exista o derivare A =+=> AB pentru B E (T U N)*. Descrierea algoritmului este : i = 0 Ni = {A A --> ? E P} repeta i = i + 1 Ni = { A A --> a E P. S' --> S} altfel N' = N S' = S P' = O/ = pentru fiecare p E P executa daca p este de forma : A --> a0 B1 a1 . Xk ak Xi E {Bi. 0 <= j <= k atunci P' = P' U ({A -> a0 X1 a1 . deci este necesara o transformare. T' --> *FT' ? In acest caz derivarea va incepe sigur cu productia E -> TE' si .free. F --> (E) a Se observa ca pentru un sir de forma a + a * a. aj E ((N \ Ne) U T)*. Bi E Ne. a E N*i-1} U Ni-1 pina Ni = Ni-1 Ne = Ni daca S E Ne atunci N' = N U {S'} P' = {S' --> ?.. O analiza sintactica de tip top-down nu poate sa opereze cu o astfel de gramatica.

In acest moment se vede ca pentru F trebuie sa se aplice productia F --> a. productia A --> Sd se inlocuieste cu A --> Aad bd. Sa consideram insa gramatica : S --> Aa A --> Ac b Sd e Se observa ca este posibila urmatoarea derivare S ==> Aa => Sda. au l > k. m >= i. deci gramatica este recursiva stinga. Eliminind recursivitatea stinga se obtine : S --> Aa b. Rezulta deci ca A --> Ac Aad bd e.. uk sint toate productiile pentru Aj = elimina recursivitatea stinga intre productiile Ai = Sa consideram pasul i. Productiile Ak --> Alr care au mai ramas pentru care k < i. A' --> cA' adA' ? d. In general daca pentru un neterminal A exista productiile : A --> AB1 AB2 . se productii cu : A --> r1A' A' --> B1A' r2A' B2A' . Daca gramatica nu permite derivari de tipul A =+=> A (fara cicluri) si nu contine ? . A --> Ac Sd e Consideram pentru neterminale ordinea : S. A --> bdA' eA'.se obtine derivarea E ==> TE' ==> FT'E'.productii poate sa fie transformata in vederea eliminarii recursivitatii stinga utilizind urmatorul algoritm... Factorizare stinga . Deci se obtine E =+=> aT'E'.. . Intrare O gramatica fara cicluri si ?.. An pentru i = 1 pina la n executa pentru j = 1 pina la i . etc.. 1 <= i <= n..1 executa inlocuieste fiecare productie de forma Ai --> Aj r cu productiile Ai --> u1 r u2 r . Sa consideram de exemplu din nou gramatica : S --> Aa b.productii Iesire O gramatica echivalenta fara recursivitate stinga. Pentru i = 2. Urmeaza simbolul terminal + datorita caruia pentru T' se va aplica productia T' --> ?.. In aceasta iteratie prin variatia lui j se ajunge ca pentru orice productie de forma Ai --> Am r. ABm r1 r2 . Daca se elimina recursivitatea directa ramine m > i. Descrierea algoritmului este : Se aranjeaza neterminalele in ordinea A1... uk r unde Aj --> u1 u2 .. A. .... rn unde ri nu incepe cu A.. rnA' BmA' ? pot inlocui aceste Aceasta constructie elimina recursivitatea stinga imediata. Pentru S (i = 1) nu exista recursivitate stinga directa deci nu se face nici o modificare.

In general pentru productia A --> r u1 r u2 daca se recunoaste la intrare un sir nevid derivat din r nu se poate stii daca trebuie aleasa prima sau a doua productie... un A' este un nou neterminal. Corespunzator este utila transformarea: A --> r A'. Se aplica in mod repetat aceasta transformare pina cind nu mai exista doua alternative pentru un neterminal avind un prefix comun. Eliminarea simbolilor nefinalizati se face utilizind . Eliminarea simbolilor neterminali neutilizati Un simbol neterminal neutilizat este un simbol care nu poate sa apara intr-o forma propozitionala (inaccesibil) sau din care nu poate deriva un sir format numai din simboli terminali sau care apare intr-o forma propozitionala datorita sau impreuna cu simboli neterminali nefinalizati. Din recunoasterea simbolului a la inceputul sirului nu se poate inca trage concluzia care dintre cele doua productii corespunzatoare neterminalului E trebuie sa fie luata in considerare (abia la intilnirea caracterului + pe sirul de intrare se poate face o alegere corecta). run t (unde t reprezinta alternativele care nu incep cu r) cu : A --> r A' t A' --> u1 u2 .. in acest mod rezulta sirul de derivari : E ==> TX ==> FYX ==> aYX ==> . A' --> u1 u2. Pentru fiecare neterminal A se cauta cel mai lung prefix r comun pentru doua sau mai multe dintre productiile corespunzatoare neterminalului A.Acest tip de transformare este util pentru producerea unei gramatici potrivite pentru analiza sintactica top down de tip determinist.. Daca r =/ ? atunci se inlocuiesc productiile de forma A --> ru1 ru2 . Reluind exemplul considerat se obtine : E X T Y F --> --> --> --> --> TX +E ? FY *T ? a (E) Deci in analiza sirului a + a la intilnirea operatorului + pentru neterminalul Y se va utiliza productia Y --> ?. Algoritmul de factorizare functioneaza in modul urmator. Ideea este ca daca nu este clar care dintre productiile alternative poate sa fie aplicata pentru un neterminal se va amina luarea unei decizii pina cind s-a parcurs suficient din sirul de intrare pentru a se putea lua o decizie. Sa consideram de exemplu productiile : E --> T + E T T --> F * T F F --> a (E) Sa presupunem ca incercam sa construim sirul derivarilor pornind de la simbolul de start al gramaticii.. e..

Intrare O gramatica G = (N. S) care urmatoarele conditii : (i) L(G) = L(G') (ii) V. S) Iesire O gramatica G' = (N'. se observa ca B este un simbol neterminal inaccesibil. Eliminarea simbolilor inaccesibili se poate face utilizind urmatorul algoritm. A --> a. B --> a}. S) Iesire O gramatica G' = (N'. Sa consideram o gramatica avind productiile : P = {S --> A.A E N'. A -> b. Aparent conditia de inaccesibilitate consta din ne aparitia in partea dreapta a unei productii. B) lista = lista U {B} = = = N' = lista elimina din gramatica toate productiile care corespund unor simboli din N \ lista. A =+=> w. B --> cC. T. P'. . Descrierea algoritmului este : N0 = O/ i = 0 repeta i = i + 1 Ni = { A A --> a E P si a E (Ni-1 U T)* } U Ni-1 pina Ni = Ni-1 N' = Ni P' C_ P contine numai productiile din P care au in partea stinga simboli din N' Prin inductie asupra numarului de pasi se poate demonstra corectitudinea algoritmului. exista w E (N U T)*. T. P'. T. T. S) cit timop stiva nu este vida executa A = pop(stiva) pentru fiecare neterminal B din partea dreapta a unei productii pentru A executa daca B nu este in lista atunci push(stiva. P. C --> bB} se observa ca este necesara o conditie mai puternica.urmatorul algoritm : Intrare O gramatica G = (N.A E N. P. S => w si A apare in w Descrierea algoritmului este: initializare stiva lista = {S} push(stiva. Daca insa consideram o gramatica avind productiile: {S -->A. w E T*. S) care urmatoarele conditii : satisface satisface (i) L(G) = L(G') (ii) V.

In acest caz nu exista ?-productii cu exceptia cel mult a unei ?-productii corespunzatoare simbolului de start al gramaticii.. Daca se aplica intii algoritmul pentru eliminarea simbolilor nefinalizati. O forma particulara de gramatica de tip Q este forma normala Greibach. Ordinea in care se aplica acesti algoritmi nu este indiferenta. Substitutia de inceputuri(corner substitution) Anumite metode de analiza sintactica presupun ca partea dreapta a fiecarei productii care nu este sirul vid sa inceapa cu un terminal. Sa consideram de exemplu gramatica cu productile : S --> a A.Prin inductie asupra numarului de pasi se poate determina corectitudinea algoritmului. 1 <=i. Prin eliminarea simbolilor inaccesibili ramine numai productia S --> a. O gramatica independenta de context pentru care este indeplinita conditia ca partea dreapta a oricarei productii incepe cu un terminal sau este sirul vid se numeste gramatica de tip Q. A --> AB.. Utilizind algoritmii pentru eliminarea simbolilor nefinalizati si cel pentru eliminarea simbolilor inaccesibili se obtine o gramatica care nu contine simboli neutilizati. Sa presupunem ca o gramatica are productile: P --> a1 a1 a2 a2 . g. se obtine: lista --> a(numar) lista *elem lista elem --> a(numar) *elem a Sa realizam si factorizarea productiilor neterminalului lista: lista --> aX *elem lista X --> (numar) lista ? elem --> a(numar) *elem Se observa ca in acest caz in functie de simbolul terminal curent se poate selecta productia urmatoare pentru derivare. ramin productiile S --> a si B --> b. an an ? unde ai E T. Daca insa se aplica intii algoritmul pentru eliminarea simbolilor inaccesibili si apoi cel pentru eliminarea simbolilor nefinalizati vor ramine pina la sfirsit ambele productii S --> a si B --> b. In forma normala Greibach productiile sint de forma A --> a a cu a E T si a E N*. In cazul in care aceasta productie exista simbolul de start al gramaticii nu apare in partea dreapta a nici unei productii. j <= n. B --> b. i =/ j ==> ai =/ aj. O procedura care recunoaste sirurile derivate din P este de forma: . Sa consideram de exemplu gramatica avind productiile: lista --> elem lista a elem --> a(numar) *elem Sa inlocuim aparitia neterminalului elem in prima productie.

a2 . < An. Bm a unde Aj --> B1 . Xi' .. an default: /* ? . Se defineste intii o relatie de ordine asupra neterminalelor unei gramatici. B m (se observa ca B1.p() { switch (caracter_urmator) { case a1 : avans(). Iesire O gramatica G' in forma normala Greibach Descrierea algoritmului este: Se construieste relatia de ordine asupra N astfel incit N = {A1.. Xk = = = Prin inductie asupra numarului de pasi se poate demonstra ca algoritmul realizeaza transformarea dorita.1 pina la 1 pas = -1 executa fiecare productie de forma Ai --> Aj a cu i < j se inlocuieste cu Ai --> B1 a . a1 /* tratare a1 */ case a2 : avans()...... Considerind aceasta relatie se observa ca se obtine o relatie partiala de ordine care poate sa fie extinsa la o relatie liniara de ordine. In acest ultim caz simbolul de start al gramaticii nu apare in partea dreapta a nici unei productii. A2. inlocuieste productia p cu p' = A --> aX1 . Si anume A < B daca exista o productie A --> B a.. Bm incep cu terminale) = pentru fiecare productie de forma p = A --> a X1 ... An} si A1 < A2 < . nu are cicluri.... In acest caz algoritmul este: Intrare O gramatica G independenta de context care nu este recursiva stinga.. nu are simboli neutilizati si nu are ?-productii cu exceptia cel mult a unei ?-productii corespunzatoare simbolului de start al gramaticii.. case an : avans().productie */ } } Se poate elabora un algoritm pentru construirea unei gramatici in forma normala Greibach pentru o gramatica independenta de context care nu este recursiva stinga.... Daca gramatica pentru care se construieste aceasta relatie nu este recursiva dreapta atunci productiile celui "mai mare" neterminal incep cu simboli terminali.. Xk executa pentru i = 1 pina la k executa daca Xi E T atunci N = N U {Xi'} P = P U { Xi' --> Xi}. . pentru i = n . .. De exemplu pentru gramatica expresiilor aritmetice in forma fara ?-productii: .

Pe de alta parte limbajul L2' = {anbn n > 1}. Rezulta urmatoarea gramatica in forma normala Greibach: E --> (EAT'E' a T' E' (EAE' E' --> +TE' +T T --> (EA T' a T' (EA a.3. Constructii dependente de context Anumite constructii specifice limbajelor de programare de nivel inalt nu pot sa fie descrise prin limbaje independente de context. +T. De asemenea o gramatica regulata nu poate sa "numere" decit pina la o limita finita. pentru care toate productiile incep cu un terminal.1. eventual de tipuri diferite. Rezulta modificarea productiilor pentru T: T --> (E) T' a T' (E) a. Fie limbajul L2 = {anbmcndm n > 1. Deci o gramatica independenta de context poate sa "numere" doi termeni dar nu trei sau mai multi. Fie limbajul L1 = {wcw w E {0. De exemplu sa consideram limbajul: { anxn n > 1 } . F. pentru E se obtine: E --> (E)T'E' a T' E' (E)E' aE' (E)T' aT' (E) a De asemenea E' nu se modifica. L1 nu poate sa fie generat de o gramatica independenta de context. Urmeaza T' care nu necesita transformari. 1. Acest limbaj realizeaza abstractizarea corespondentei ca numar intre numarul de parametrii cu care au fost declarate procedurile si numarul de parametrii cu care se utilizeaza acestea. T' --> *FT' *F F --> (EA a A --> ) aE' (EAT' aT' (EA a 1. Din acest motiv conditia ca un identificator sa fie definit inainte de a fi utilizat nu pot fi verificate prin analiza sintactica. 2. Se porneste de la F. deci va fi verificat de catre analiza semantica. m > 1}.1. Sa consideram citeva exemple : 1. Este utila gasirea unui criteriu prin care sa se indice tipul restrictiv al gramaticilor care pot sa descrie un limbaj dat. Propietati ale limbajelor independente de context Dupa cum s-a vazut acelasi limbaj poate sa fie descris de mai multe gramatici. Nici acest limbaj nu pot fi descris de o gramatica independenta de context.4. *F a Relatia de ordine liniara poate sa fie E' < E < T' < T < F.E --> E'--> T --> T'--> F --> T E' +TE' FT' *FT' (E) T . poate sa fie descris de gramatica : S --> a S b a b.1}*}. Acest limbaj realizeaza abstractizarea conditiei ca un identificator sa fie declarat inainte de a fi utilizat.

T.. Urmatoarea teorema ofera un criteriu de stabilire a tipului probabil pentru gramaticile care genereaza un limbaj dat. . in T in modul urmator: (1) n1 este nodul radacina pentru T (2) daca ni are un singur descendent direct din care deriveaza un sir care contine pozitii marcate atunci ni+1 va fi acest nod.. P. (4) daca ni este o frunza s-a ajuns la sfirsitul caii. . In caz contrar bi . (4) exista un neterminal A astfel incit: S =+=> uAy =+=> uvAxy =+=> u vi A xi y =+=> u vi w xi y pentru orice i > 0 . z > k si k sau mai multe pozitii din sirul z sint marcate atunci sirul z poate sa fie scris sub forma z = uvwxy astfel incit sint indeplinite urmatoarele conditii: (1) in w apare cel putin o pozitie marcata.. Deoarece z > k inseamna ca arborele va contine cel putin o cale mai lunga sau egala cu 2m + 3. (3) in vwx apar cel mult k pozitii maracte. Daca ni nu este nod de ramificatie atunci ni+1 are toti atitia descendenti marcati ca si ni. Fie k = l2m + 3. Daca ni este un nod de ramificatie atunci ni+1 are cel putin 1/l descendenti marcati fata de nodul ni. Fie b1.. Teorema Ogden Pentru orice gramatica independenta de context G = (N. n1 are cel putin l2m + 3 descendenti marcati (k = l2m + 3). Daca exista egalitate se alege dintre nodurile cu acelasi numar nodul care apare cel mai in dreapta.... Demonstatie Fie m = Card(N) si fie l lungimea celei mai lungi parti dreapta a unei productii din P. np este calea construita. . Evident. (3) daca ni este un nod de ramificare se alege ca ni+1 nodul descendent direct al nodului ni care are numarul maxim de pozitii marcate in sirul derivat.Se pune problema daca exista o gramatica independenta de context care sa-l genereze. S) exista un numar intreg k > 1 astfel incit daca z E L(G). Sa presupunem ca n1. Sa marcam cel putin k pozitii din z. Sa consideram arborele de derivare T pentru un sir z E L(G) astfel incit z > k. Sa demonstram prin inductie asupra valorii numarului i ca daca calea n1... ni contine r noduri de ramificare atunci ni+1 are cel putin l2m+3-r descendenti marcati. Pentru i = 0 se obtine r = 0. Se numeste nod de ramificare in T un nod care are cel putin doi descendenti directi astfel incit din fiecare din ei se pot deriva siruri ce contin pozitii marcate. Se construieste o cale n1... numar intreg. b2m+3 noduri de ramificatie dintre n1. . (2) fie u si v contin fiecare cite cel putin o pozitie marcata fie acest lucru este valabil pentru x si y.. n2.. . np. Vom spune ca bi este un nod de ramificatie stinga daca un descendent direct al nodului b care nu face parte din cale are un descendent marcat aflat la stinga nodului np. np cel putin 2m + 3 noduri de ramificatie. In plus np este o frunza (deci nu este nod de ramificatie) si deci p > 2m + 3. n2.. b2. . Pentru ca n1 are l2m + 3 descendenti marcati exista in calea n1..

Pentru conditia (3) se observa ca b1 este cel de al 2m + 3 nod de ramificatie pornind de la sfirsit poate avea maximum k pozitii marcate.. De asemenea v va contine cel putin un terminal marcat (conditie 2).. . Deoarece Card(N) = m. si etichetele pentru lf si lg sint aceleasi. deci L nu poate sa fie generat de o gramatica independenta de context.. Atunci exista o constanta k caracteristica limbajului astfel incit daca z E L si z >= k. Rezulta ca este indeplinita conditia (4). vwx <= k si pentru orice i... exista doua noduri intre l2. Dupa k x k urmatorul patrat perfect este (k + 1) x (k + 1) care este mai mare deci k x k + k. Fie A neterminalul respectiv.... Sa utilizam rezultatul obtinut pentru a studia limbajul: L = {an x n n > 1} sa presupunem ca L este independent de context. . . Sa presupunem ca cel putin m + 2 noduri intre b1.. Cazul in care conditia nu este indeplinita este cazul in care cel putin m + 2 noduri dintre b1. b2m + 3...lm+2 cele mai din stinga noduri de ramificatie stinga dintre b1. Deci S =+=> uAy. . Se observa ca A =*=> w. Fie l1. Rezulta ca uv2wx2y E L.este un nod de ramificare dreapta. Se observa ca u are cel putin un terminal marcat (lf a fost ales pornind de la l2). atunci z poate sa fie scris sub forma z = uvwxy cu vx =/ ?. uviwxiy E L. b2m + 3 sint noduri de ramificatie dreapta si se trateaza similar. cu u terminalele obtinute la stinga sirului derivat din A iar y terminalele obtinute la dreapta sirului derivat din A. Corolar (lema de pompare) Fie L un limbaj independent de context... .. Deoarece vwx <= k rezulta 1 < vx < k deci k x k < uv2wx2y < k x k + k. Se observa ca lf este un descendent pentru b1. adica uv2wx2y nu poate sa fie un patrat perfect. lm+2 pe care sa le notam lf si lg astfel incit f < g.. b2m + 3 sint noduri de ramificatie stinga. De asemenea conditia (1) este satisfacuta cel putin prin np.. =+=> uviwxiy. Rezulta deci: S =+=> uAy =+=> uvAxy =+=> uv2Ax2y =+=> .. Inseamna ca exista un numar k astfel incit daca n * n >= k atunci anxn = uvwxy astfel incit v si x nu sint amindoua siruri vide si vwx < k. . Sa presupunem ca n = k ( k * k > k). S / \ /\ \ / \l \ / \1 \ / l _\ \ / f /\ \ / / \ \ / / __\ l \ / / /\ \ g \ / / / \ \ \ / / / \ \ \ / u / v/ w \x \ y \ Daca se sterg toti descendentii pentru lf se ajunge la frontiera uAy.

6. Expresiile regulate au o serie de proprietati. t expresii regulate. Descrierea multimiilor regulate se poate face cu ajutorul expresiilor regulate. 8. 9. 4. Sa consideram de exemplu ecuatia: . 3. expresii regulate. Spunem ca a = B daca si numai daca a si B descriu aceleasi multimi regulate. Daca a E T atunci {a} este o multime regulata asupra alfabetului T. concatenare (PQ) sau inchidere P*. ? este o expresie regulata care descrie multimea {?}. o este o multime regulata asupra alfabetului T. 2. (p)* este o expresie regulata care descrie multimea P*. 4. Nimic altceva nu este o multime regulata Se observa deci ca o submultime a multimii T* este o multime regulata asupra alfabetului T daca si numai daca este multimea vida. B. De exemplu expresia regulata (0 (1(0)*)) poate sa fie scrisa si sub forma 0 10*. urmeaza operatia de concatenare cel mai putin prioritara fiind operatia + ( ). 7. a B = B a a(Bt) = (aB)t (a B)t = at a* = a a* a a = a 2. In particular pp* este notat cu p+. PQ. Multimi regulate. 5. 4. Fie a.2. a (B t) = (a B) a(B t) = aB at a? = ?a = a (a*)* = a* t Bt Utilizind expresii regulate se pot construi si rezolva ecuatii cu solutii expresii regulate. De exemplu expresia (0 1)* reprezinta multimea {0. expresia regulata : (00 11)*((01 10)(00 11)*(01 10)(00 11)*)* reprezinta multimea care contine toate sirurile formate din 0 si 1 si care contin un numar par din fiecare simbol. P* sint multimi regulate asupra alfabetului T.q sint expresii regulate care descriu multimile P si Q atunci : a. Fie T un alfabet finit.1}*.1. (pq) este o expresie regulata care descrie multimea PQ. Daca P si Q sint multimi regulate atunci PUQ. daca p. 3. este o multime care contine un singur simbol din T sau poate sa fie obtinuta din aceste doua tipuri de multimi utilizind operatiile de reuniune (P U Q). 3. b. nimic altceva nu este o expresie regulata. 2. Sint adevarate urmatoarele proprietati : 1. O expresie regulata este la rindul ei definita recursiv in modul urmator (prin analogie cu definitia multimiilor regulate) : 1. Se numeste multime regulata asupra alfabetului T multimea construita recursiv in modul urmator : 1. (p + q) sau (p q) este o expresie regulata care descrie multimea P U Q. a E T este o expresie regulata care descrie multimea {a}. c. Intre operatorii utilizati in descrierea multimilor regulate exista o serie de relatii de precedenta si anume cea mai prioritara operatie este operatia de inchidere (notata cu *).

A) cu P = {A ->1A 0B. Demonstratia acestei teoreme se face prin constructie. Propozitie Daca G este o gramatica regulata atunci L(G) este o multime regulata. Sa inlocuim in ecuatie pe X cu expresia regulata: a*(b + t) Se obtine: a*(b + t) = = = = a[a*(b + t)] + b = a+b + a+t + b = (a+ + ?)b + a+t = a*b + a*t a*(b + t) Se numeste punct fix al unei ecuatii cea mai mica solutie a ecuatiei respective. B -> 0B 1C. C}.X = aX + b unde a. P. Se poate verifica usor ca X = a*b este o solutie a acestei ecuatii. Se cere sa se construiasca expresia regulata care genereaza acelasi limbaj ca si G.1}. B.b si X sint expresii regulate. {0. Se pot scrie urmatoarele ecuatii: A = 1A + 0B B = 0B + 1C C = 0B + 1A + ? Din prima ecuatie se obtine: A = 1*0B Din a doua ecuatie se obtine: B = 0*1C Inlocuind in A se obtine: A = 1*00*1C = 1*0+1C Inlocuind in a treia ecuatie se obtine : C = 0+1C + 1+0+1C + ? C = (? + 1+)0+1C + ? = 1*0+1C C = (1*0+1)* Rezulta: A = 1*0+1 (1*0+1)* A = (1*0+1)+ Multimea regulata descrie sirurile de 0 si 1 care se termina cu . Daca a este o expresie regulata care poate sa genereze sirul vid atunci solutia prezentata anterior nu este unica. Sa consideram de exemplu gramatica: G = ({A. C->0B 1A ?}.

Se observa ca s-a ajuns la aceasi gramatica cu cea initiala (prin redenumirea neterminalelor).subsirul 01.3. Construirea expresiilor regulate corespunzatoare atomilor lexicali reprezinta prima etapa in proiectarea unui analizor lexical. o unitate de control si o memorie auxiliara. . in majoritatea limbajelor de programare modul de scriere al numelor si al identificatorilor pot sa fie descrise de gramatici respectiv de expresii regulate. Rezulta deci ca expresiile regulate reprezinta o metoda alternativa de tip generare pentru definirea limbajelor regulate. 1. Sa transformam aceasta gramatica prin substitutie de inceputuri: S --> 0AB A --> 0A B --> 01 Se obtine: S --> 0S 1S 01 1AB 1A B ? Utilizind factorizarea: S --> 0X X --> S 1S 1 Din nou prin inlocuire de capete se obtine: X --> 0X 1S 1 Aplicind factorizarea: X --> 0X 1Y Y --> S ? Rezulta gramatica descrisa de productiile: S --> 0X X --> 0X Y --> 0X 1S 1Y 1S ?. Evident o expresie mai simpla pentru descrierea aceluiasi limbaj este: (0 1)*01 Se observa ca se poate considera ca limbajul se obtine prin concatenarea a doua limbaje unul descris de expresia (0 1)* si celalalt descris de expresia 01. Rezulta urmatoarea gramatica: S --> AB A --> 0A B --> 01 1A ? Se observa ca gramatica obtinuta nu este regulata. Limbajele definite de gramatici regulate sint utilizate la nivelul analizei lexicale. Acceptoare Un acceptor este un dispozitiv format dintr-o banda de intrare.

an +--------------\ cap de citire \ +---------+ unitate de control +---------+ +-----------+ memorie auxiliara +-----------+ Banda de intrare este formata din elemente in care se inscriu simbolii din sirul de intrare.starea unitatii de control.deplasarea capului de citire la stinga sau la dreapta sau mentinerea capului de citire pe aceeasi pozitie si / sau. Rezulta ca o miscare a acceptorului poate sa fie precizata prin configuratia initiala (inainte de miscare) si cea finala (dupa executia miscarii). Se spune ca dispozitivul a acceptat un sir de intrare w daca pornind din configuratia initiala ajunge in configuratia finala. . organizarii si accesului la memoria auxiliara se obtin diferite cazuri particulare de acceptoare. De asemenea in cadrul executiei unei miscari unitatea de control are acces la informatia din memoria auxiliara pe care o poate modifica. Daca pentru o configuratie data sint posibile mai multe miscari atunci spunem ca acceptorul este nedeterminist altfel este determinist. . Comportarea unui acceptor poate sa fie descrisa in functie de configuratiile acestuia. In general un astfel de acceptor are o configuratie initiala in care unitatea de control este intr-o stare initiala. O configuratie este formata din urmatoarele informatii : . De asemenea acceptorul are o configuratie finala pentru care capul de citire este situat pe simbolul cel mai din dreapta de pe banda de intrare. Daca .+--------------a0 a1 . notiunea de acceptare poate sa fie conditionata si de ajungerea intr-o anumita stare sau de un anumit continut al memoriei auxiliare. Exprimind diferite restrictii asupra benzii de intrare.. Evident daca acceptorul este nedeterminist dintr-o configuratie initiala pot avea loc mai multe evolutii. . O miscare a acceptorului este formata din : . La un moment dat capul de citire este fixat pe un simbol. Functionarea dispozitivului este data de miscarile acestuia.continutul memoriei.. Eventual. . capul de citire este fixat pe simbolul cel mai din stinga iar memoria are un continut initial specific.memorarea unei informatii in memoria auxiliara si / sau.modificarea starii unitatii de control. Se observa ca acest model este foarte general. Capul de citire se poate deplasa la stinga sau la dreapta in cadrul unei astfel de miscari sau poate sa ramina nemiscat.continutul benzii de intrare si pozitia capului de citire.

automatul este nedeterminist. atunci (s.1} {0} ------------+----------+---------. 1. Acelasi automat finit poate sa fie descris de urmatorul graf de tranzitie : a --\ / +---+ +---+ +---+ +---+ . In definirea unui automat finit se pot utiliza doua moduri de reprezentare. care sint acceptoare pentru limbajele independente de context.m : S x (T U {?}) -> P(S) este functia partiala a starii urmatoare. deci asa cum a fost definit. F) unde : .F = {3} 1 {2} ------------+----------+---------2 {3} ----------------------------------+ Se observa ca in fiecare intrare este specificata multimea starilor urmatoare in care se trece pentru starea si simbolul corespunzator intrarii respective. printr-o tabela de tranzitie sau printr-un graf. T. Dintre acestea cele mai cunoscute sint automatele finite care sint acceptoare pentru limbaje regulate si automatele cu stiva (push-down). Daca pentru s E S.1.a) se numeste tranzitie.exista intre acestea una pentru care se ajunge la o configuratie finala atunci se spune ca dispozitivul a acceptat sirul. .3.S este multimea finita a starilor. s0. Se observa ca pentru o combinatie stare(s E S). Limbajul definit de catre un acceptor este format din multimea sirurilor acceptate de catre acesta.a) este definita. . m. Poate sa fie descris sub forma urmatoarei tabele : +---------------------+ simbol de intrare stare a b ------------+--------------------0 {0. daca a = ? atunci (s. . . Automate finite Un automat finit este un obiect matematic AF = (S.F C_ S este o multime de stari numita multimea starilor finale (de acceptare).a) se numeste ?tranzitie. Automatele finite sint acceptoare fara memorie auxiliara iar automatele cu stiva sint acceptoare pentru care accesul la memoria auxiliara se face conform unui mecanism de tip stiva. Sa consideram de exemplu automatul care accepta limbajul definit de expresia (a b)* abb. Pentru fiecare tip de gramatica din ierarhia Chomsky exista o clasa de acceptoare care definesc aceasi clasa restrictiva de limbaje. a E T m(s.T este o multime finita numita alfabet de intrare. intrare(i E I) pot sa corespunda mai multe stari urmatoare.s0 E S este o stare numita stare de start.

De remarcat modul in care a fost specificata starea finala.i) E S x T este definita cel mult o tranzitie. automatul care accepta limbajul . Se observa ca sint satisfacute urmatoarele restrictii: 1. pentru un sir de intrare dat. Pentru expresia ?. astfel incit sirul simbolilor care eticheteaza arcele care formeaza aceasta cale este sirul de intrare. V-(s. In cazul automatelor finite deterministe definitia functiei starii urmatoare se modifica: m : S x T -> S. Pentru construirea automatului se identifica in structura expresiei r structurile care in mod recursiv compun structura expresiei si se construiesc automatele finite nedeterministe (AFN) elementare corespunzatoare. Se spune ca un automat finit accepta un sir de intrare daca exista o cale in graful de tranzitie intre nodul care reprezinta starea de start si un nod care reprezinta o stare finala. De exemplu sirul aabb este acceptat de automatul descris anterior. direct Intrare O expresie regulata r asupra unui alfabet T Iesire Un automat finit nedeterminist (N) care accepta limbajul L(r). intre doua noduri exista un arc etichetat cu un simbol de intrare daca si numai daca se poate trece din starea reprezentata de primul nod in starea reprezentata de al doilea nod la aplicarea la intrare a simbolului cu care este etichetat arcul.1.1. in graful de tranzitie exista cel mult o cale care porneste din starea de start si duce intr-o stare de acceptare. Constructia unui automat finit nedeterminist care accepta limbajul descris de o expresie regulata data Algoritmul pe care il vom prezenta utilizeaza structurile din definitia expresiilor regulate. nu exista ?-tranzitii. 1. 1. 2.start a b b +-+ --------> 0 --> 1 --> 2 --> 3 +-+ +---+ +---+ +---+ +---+ / \ --b Se observa ca pentru fiecare stare exista cite un nod.3. care va executa urmatoarele miscari : a a b b 0 --> 0 --> 1 --> 2 --> 3 Se observa ca pentru acelasi sir de intrare exista si alte secvente de intrari care insa nu duc intr-o stare de acceptare : a a b b 0 --> 0 --> 0 --> 0 --> 0 Un caz particular al automatelor finite este dat de automatele finite deterministe (AFD). Se observa ca in acest caz.

-+--> ---.corespunzator este : +---+ +-----+ start ? +---+ --------> i ------> f +---+ +---+ +-----+ 2. a. corespunzator este : automatul care accepta limbajul +---+ +-----+ start a +---+ --------> i ------> f +---+ +---+ +-----+ 3.--> ---/ +---+ \ ? / +---+ +-----+ \ +---+ / \ +-----+ / ------------------------\ +---+ -> i f \ ------------------------/ +---+ +---+ \ / +-----+ \ +---+ +-----+ / \ ? N(t) +---+ / ? ----------> -. .--> f ---+---+ +---+ +---+ +-----+ --------------+-------------------------------------Se observa ca in acest caz starea finala a automatului corespunzator expresiei r coincide cu starea initiala a automatului corespunzator expresiei t. pentru expresia regulata r t limbajul corespunzator este acceptata de : ------------------------+---+ +-----+ ? N(r) +---+ ----------> -.t pentru care s-au construit automatele finite nedeterministe corespunzatoare N(r) si N(t).--> ---/ +---+ +---+ +-----+ ------------------------b. Pentru expresia a. Fie doua expresii regulate r. pentru expresia regulata rt limbajul corespunzator este acceptata de : -----------------------------------------+----------+---+ +---+ +-----+ N(r) N(t) +---+ ----------> i --.

a. pentru expresia regulata r* limbajul corespunzator este acceptata de : ? +-<------------+ ----- -------------- ----+---+ +---+ +-----+ ? N(r) ? +---+ ----> i ----------> --- ----> --------> f +---+ +---+ +---+ +---+ +-----+ /\ -------------------------? +---------------------------------------------+ +---+ d. pentru expresia (r) limbajul corespunzator este acceptat de automatul care accepta N(r). Se observa ca pentru fiecare AFN - elementar se adauga cel mult o stare initiala si o stare finala. Corespunzator pentru o expresie regulata data automatul va avea un numar de stari egal cu maxim dublul numarului de simboli de intrare care apar in expresie. Compunerea acestor automate elementare va produce evident un automat care recunoaste limbajul generat de expresie. De exemplu pentru expresia regulata : (a b)*abb se obtine : pentru fiecare a din expresie : +-----+ a +---+ --------> i ------> f +---+ +---+ +-----+ pentru fiecare b din expresie : +-----+ b +---+ --------> i ------> f +---+ +---+ +-----+ pentru a b : +---+ +-----+ a +---+ ------> ---/ +---+ \ ? / +---+ +-----+ \ +---+ / \ +-----+ / \ +---+ -> i f \ / +---+ +---+ \ / +-----+ \ +---+ +-----+ / \ ? b +---+ / ? ----------> ------> ---/ ? ----------> +---+ +---+

+---+ In final se obtine : ? ---------------+ /

+---+ +-----+

+-+ +-+ ? a / / --> 2 -> 3 \ ? / / \ +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ ? / ? a b b ---> 0 -> 1 6 -> 7 -> 8 -> 9 -> 10 \ / -+-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ ? b /? /\ \ --> 4 -> 5 / / \ / \ +-+ +-+ / \ ? / -------------------/ 1.3.1.2. Conversia unui automat finit nedeterminist (AFN) intr-un automat finit determinist(AFD) Din exemplele anterioare s-a observat ca un acelasi limbaj reprezentat de expresia regulata (a b)* abb poate sa fie recunoscut de doua automate diferite - unul nedeterminist si unul determinist. Propozitie Pentru orice automat finit nedeterminist exista un automat finit determinist care accepta acelasi limbaj. Avind in vedere aceasta echivalenta intre cele doua automate se pune problema cum se poate construi un automat determinist echivalent unui automat nedeterminist dat. In cele ce urmeaza vom considera ca automatul finit nedeterminist a fost construit pornind de la o expresie regulata pe baza constructiei prezentate in paragraful anterior. Algoritmul care construieste automatul determinist utilizeaza o metoda de construire a submultimiilor unei multimi date. Diferenta intre automatele deterministe si cele nedeterministe este data de cardinalitatea functiei m. Automatul determinist se va construi calculind in mod recursiv starile acestuia, simulind in paralel toate evolutiile posibile pe care le poate parcurge automatul nedeterminist. Starea initiala a automatului finit determinist va corespunde multimii starilor din automatul nedeterminist in care se poate ajunge pornind din starea initiala s0 si utilizind numai ?tranzitii. Orice stare s' a automatului determinist corespunde unei submultimi S' C_ S a automatului nedeterminist. Pentru aceasta stare si un simbol de intrare a E I, m(s',a) = {s E S (= q ES')(s = m(q,a))}. Rezulta deci ca in functionarea AFD care simuleaza de fapt functionarea AFN se urmaresc simultan toate "caile" pe care poate evolua automatul finit nedeterminist. Algoritmul care construieste automatul finit determinist echivalent cu un automat nedeterminist dat utilizeaza doua functii : ?-inchidere si move. Functia ?-inchidere : P(S) ->P(S) determina pentru fiecare

/

multime S' < S setul starilor in care se poate ajunge datorita ?tranzitiilor. Considerind o stare q a automatului finit determinist (AFD), aceasta reprezinta de fapt o submultime S'< S al automatului nedeterminist. Notam cu ?-inchidere(q) = U ?-inchidere({s}) sES' unde daca s E S este o stare care nu are ?-tranzitii atunci: ?-inchidere({s}) = {s} altfel ?-inchidere({s}) = {s} U U ?-inchidere({s'}) s'E m(s,?) Constructia functiei ?-inchidere pentru o multime S' se poate face utilizind urmatorul algoritm : A = S' B = O cit timp A \ B =/ O executa fie t E A \ B B = B U {t} pentru fiecare u E S astfel incit m(t,?) = u executa A = A U {u} = = ?-inchidere(S') = A Functia move : P(S) x T -> P(S) este utilizata pentru constructia starii urmatoare a automatului determinist. Astfel pentru o stare q a automatului determinist, caruia ii corespunde o multime S' < S, si o intrare a E I, move(q,a) = U m(s,a) sES' Constructia automatului determinist se face prin constructia unei tabele de tranzitii tranz_AFD si a unei multimi de stari stari_AFD. stari_AFD = {?-inchidere({s0})} A = O cit timp stari_AFD \ A =/ O executa fie t E stari_AFD \ A A = A U {t} pentru fiecare a E T executa B = ?-inchidere(move(t,a)) stari_AFD = stari_AFD U {B} tranz_AFD[t,a] = B = = Fie automatul nedeterminist : ? ---------------+ /

7} ?-inchidere({5}) -----------+----+----+-------------------------------------q4 q2 q5 {1. 2.3. 7}.6.2.7.5.6.2.1.2.6.a)=q2.2. Continuind se obtine urmatoarea tabela de tranzitie : stare intrare multime corespunzatoare AFN a b -----------+----+----+-------------------------------------q1 q2 q3 {0.4.7}).a)) = ?-inchidere({3.8} ?-inchidere({3. q2 = {1.8}) = = {1.7.9} ?-inchidere({5. 1.4.8} atunci tran_AFD(q1.5.4.7.8}.1.4.2.6. ?-inchidere(move({0.6.5.10} ?-inchidere({5.2.8}) -----------+----+----+-------------------------------------q3 q2 q3 {1.7}.+-<--------+ a a +--<--------------------+ b / .4. Daca q1 = {0.6.4.3.7.7} ?-inchidere({0}) -----------+----+----+-------------------------------------q2 q2 q4 {1.+-+ +-+ ? a / / --> 2 -> 3 \ ? / / \ +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ ? / ? a b b ---> 0 -> 1 6 -> 7 -> 8 -> 9 -> 10 \ / -+-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ ? b /? /\ \ --> 4 -> 5 / / \ / \ +-+ +-+ / \ ? / -------------------/ Se observa ca ?-inchidere(0) = {0.9}) -----------+----+----+-------------------------------------q5 q2 q3 {1.7.10}) -----------------------------------------------------------Graful automatului finit determinist care a rezultat este : b --\ / +---+ b --> q3 <---------------------+ / ++---+ /a +---+ start / +---+ +---+ +------+ ------.4. 4.4.4.1.2.3.2.2.q1 a \/ b b +----+ -----> q2 ------> q4 -----> q5 +---+ +----+ +---+ +---+ +------+ /\ a -.

3.Se observa ca s-a obtinut un automat cu 5 stari fata de 4 stari cit avea automatul finit determinist cu care s-au exemplificat automatele finite deterministe. *. lastpos. followpos. firstpos. Pentru a simplifica constructiile consideram pentru orice expresie regulata si un simbol de sfirsit pe care il vom nota cu # astfel incit orice expresie regulata r va fi reprezentata de r#. b / \ / \ * a / \ / a \ b Se observa ca in nodurile interioare apar operatori iar frunzele sint reprezentate de catre simbolii de intrare. / \ / . Primele 3 functii sint definite asupra nodurilor din arborele care descriu expresia regulata. Se observa ca exista trei operatori ( .3. / \ / . / \ / . Functia nullable este o functie logica care are valoarea adevarat daca si numai daca subarborele . b / \ / \ . / \ / \ .). Constructia unui automat finit determinist care accepta limbajul descris de o expresie regulata data O expresie regulata poate sa fie reprezentata sub forma unui arbore. de exemplu acest cod poate sa fie reprezentat de pozitia simbolului respectiv in expresia regulata. Reluind pentru expresia anterioara va rezulta graful : . Utilizind aceste coduri se construiesc patru functii : nullable.1. Deci algoritmul utilizat nu produce neaparat o solutie optima. / \ / * / \ / a 1 \ b 2 \ a 3 4 \ b 5 \ b 6 \ # Vom atasa fiecarei frunze un cod unic. De exemplu pentru expresia regulata (a b)*abb rezulta arborele: . . 1.

2.corespunzator nodului respectiv reprezinta o expresie regulata care poate sa genereze sirul vid.2. c.3} lastpos(x) = {3} (a 1 b)* a 2 3 valoare inceput expresia exemplu Functia lastpos aplicata unui subarbore are ca valoare setul codurilor frunzelor corespunzatoare pozitiei de sfirsit pentru subsirurile care pot sa fie generate de catre expresia regulata corespunzatoare subarborelui respectiv. Astfel functia nullable aplicata subarborelui : / \ a b are valoarea fals in schimb aplicat asupra subarborelui : * a are valoarea adevarat. Daca i este un cod atunci followpos(i) este multimea codurilor j care satisfac urmatoarea conditie. astfel incit i este codul corespunzator frunzei datorita careia a aparut simbolul c iar j este codul corespunzator frunzei datorita careia a aparut simbolul d. firstpos si lastpos sint urmatoarele : forma nod nullable(n) firstpos(n) lastpos(n) -----------------+--------------+-----------------+------------n este o frunza adevarat o o cu eticheta ? -----------------+--------------+-----------------+------------n este o frunza cu eticheta =/ ? fals {i} {i} . Functia followpos este definita asupra multimii codurilor frunzelor. Din expresia regulata corespunzatoare arborelui se poate genera un sir care sa contina subsirul cd. Pentru a calcula followpos trebuie sa se calculeze functiile firstposi si lastpos care la rindul lor necesita calculul functiei nullable. Regulile pentru calculul functiilor nullable. De exemplu followpos(1) = {1. De pentru nodul radacina al subarborelui : x . Functia firstpos aplicata unui subarbore are ca setul codurilor frunzelor corespunzatoare pozitiilor de pentru subsirurile care pot sa fie generate de catre regulata corespunzatoare subarborelui respectiv. d E T. / \ / * / \ / a 1 \ b 2 \ a 3 firstpos(x) = {1. followpos(i) contine toate codurile care pot sa apara imediat dupa i in aceste siruri. Altfel spus daca se considera sirurile obtinute din propozitiile din L(r) (limbajul generat de expresia regulata) prin inlocuirea simbolilor din T cu codurile asociate frunzelor din graf care le genereaza.3}.

{3} {4}b{4} / \ 4 / \ / \ {1.2.{4} {5}b{5} / \ 5 / \ / \ {1.{5} {6}#{6} / \ 6 / \ / \ {1.2} {1.2} {3}a{3} 3 {1.3} .avind codul i -----------------+--------------+-----------------+------------n nullable(c1) firstpos(c1) lastpos(c1) / \ sau U U / \ nullable(c2) firstpos(c2) lastpos(c2) c1 c2 -----------------+--------------+-----------------+------------n .3} .2.2.2. daca n este un nod corespunzator operatorului de concatenare cu subarborii c1 si c2 (respectiv stinga dreapta) atunci daca i este un cod din lastpos(c1) toate codurile din firstpos(c2) sint in multimea followpos(i).{6} / \ / \ / \ {1. daca n este un nod corespunzator operatorului *.2} / \ / \ / \ {1} a{1} {2}b{2} 1 2 . nullable(c1) daca daca nullable(c1) nullable(c2) / \ si atunci atunci / \ nullable(c2) firstpos(c1) lastpos(c1) c1 c2 U U firstpos(c2) lastpos(c2) altfel altfel firstpos(c1) lastpos(c2) ----------------------------------------------------------------forma nod nullable(n) firstpos(n) lastpos(n) -----------------+--------------+-----------------+-------------n * adevarat firstpos(c) lastpos(c) c ----------------------------------------------------------------Pentru a calcula followpos(i) care indica ce coduri pot sa urmeze dupa codul i conform arborelui se utilizeaza doua reguli : 1. 2. si i este un cod din lastpos(n) atunci toate codurile din firstpos(n) sint in multimea followpos(i). Pentru arborele anterior valorile functiilor firstpos si lastpos sint reprezentate in stinga respectiv dreapta fiecarui nod. {1.3} .3} .2} *{1.

3} 2 {1. Starile finale sint starile asociate cu simbolul #. Automatul care a rezultat. etichetind arcele in modul urmator.Singurul nod pentru care functia nullable are valoarea adevarat este nodul etichetat cu *. avind mai multe stari initiale nu se incadreaza de fapt in definitia pe care am dat-o pentru un automat finit. Automatul are ca stari initiale starile din firstpos pentru nodul radacina. Pe baza acestor valori sa calculam followpos(1).2.2. Daca intre nodul i si nodul j exista un arc acesta va fi etichetat cu simbolul care are codul j.3} 3 {4} 4 {5} 5 {6} 6 Pornind de la aceste valori se poate construi un graf in care intre doua noduri i si j exista un arc daca j E followpos(i) --\ / +---+ +---> 1 \ +---+ +---+ +---+ +-----+ +\ +---+ +---+ 3 ---> 4 ---> 5 ---> 6 +---+ +---+ /+---+ +---+ +---+ +-----+ +> 2 / +---+---+ /\ -Pe baza unui astfel de graf se poate obtine un automat finit nedeterminist fara ?-tranzitii. a --\ / +---+ a 1 \ +---+ +---+ +---+ +-----+ +\ b b # +---+ a b +---+ 3 ---> 4 ---> 5 ---> 6 +---+ +---+ /+---+ +---+ +---+ +-----+ +> 2 / a +---> . In followpos(1) vor apare codurile din firstpos pentru nodul etichetat cu * si codurile din firstpos pentru subarborele dreapta corespunzator operatorului de concatenare (followpos(1) = followpos(2) = {1.2.3}. Fiecare stare a automatului corespunde unui nod din graf. Rezulta urmatoarele valori : nod followpos -----------------------------------1 {1. Daca insa mai adaugam o stare suplimentara care sa reprezinte unica stare initiala din care pe baza unor ?-tranzitii ajungem intr-una dintre starile automatului obtinut se vede ca ne incadram in definitia considerata.

/ +---+ +---+ +------+ 1.3.6 +---+ 4 5 +----+ +---+ +---+ +------+ /\ a -.+-<--------+ a a +--<---------------------+ b)* a b b # 2 3 4 5 6 Fie q1 = firstpos(radacina) = {1. 3 -----> 3.a) = X = = = In algoritm firstpos(radacina) este valoarea functiei firstpos aplicata nodului radacina. r(2) = r(4) = r(5) = b. followpos(2) = {1.2. 1. etc. Pentru q2 si b. -----> 3. Simularea unui automat finit determinist .4}.4..2.a) = q2. ------> 3. stari_AFD = { first_pos(radacina) } A = o cit timp stari_AFD \ A =/ o executa fie t E stari_AFD \ A A = A U {t} pentru fiecare a E T executa X = U { followpos(p) r(p) = a} p E t daca X =/ o atunci stari_AFD = stari_AFD U {X} tranz_AFD(t.b) = q1. b 2. Nici aceasta constructie nu garanteaza faptul ca automatul obtinut este minim. b 1.2. r(c) este simbolul de intrare care in expresia regulata reprezentata de arbore are codul c. Pentru q1 si a se obtine q2 = followpos(1) U followpos(3) = {1.3} = q1 si tranz_AFD(q1. a 2. Se observa ca r(1) = r(3) = a. deci tranz_AFD(q1. +----+ ------> 2. Aplicind acest algoritm si rezultatele anterioare se obtine automatul finit determinist reprezentat de urmatorul graf : b b ---------<---------------------+ \/ / (a +---+ / 1 start 1.3}. 1.)).2.3. Se observa ca first_pos(radacina) corespunde cu ?inchidere(s0) iar followpos(p) reprezinta ?-inchidere(move(..+---+---+ /\ -b Mai interesant insa este faptul ca functia followpos poate sa fie utilizata pentru construirea unui automat determinist utilizind un algoritm similar celui pentru construirea submultimilor.1.

. respectiv "NU" daca D nu accepta sirul x.Intrare un AFD (D) si un sir de intrare x. caracterul_urmator care determina starea urmatoare pentru o stare si un simbol de intrare dat si respectiv caracterul urmator din sirul de intrare. In consecinta automatul va satisface urmatoarele proprietati : 1. pentru sirul ababb.1.3.c) c = caracterul_urmator = daca s E F atunci rezultat "DA" altfel rezultat "NU" = Daca aplicam acest algoritm pentru automatul : b -------------b / \ --/ \ \ / V \ +---+ +---+ +---+ +---+ start a b b +-+ --------> 0 --> 1 --> 2 --> 3 +-+ +---+ +---+ +---+ +---+ /\ ^ ^ -a +-----+ a +---------------+ a care accepta limbajul (a b)* abb. fie o ?-tranzitie sau doua ?tranzitii. 2. Simularea unui automat finit nedeterminist Prezentam in continuare un algoritm pentru simularea unui automat finit nedeterminist. 3.5. Iesire Raspuns "DA" daca D accepta sirul x. din fiecare stare pleaca fie o tranzitie pentru un simbol din alfabetul de intrare T. are o singura stare de start si o singura stare de acceptare. Se considera ca automatul a fost construit pornind de la expresia regulata utilizind prima constructie. are cel mult de doua ori mai multe stari fata de numarul de simboli si operatori care apar in expresia regulata. Algoritmul utilizeaza functiile move. Algoritmul citeste un sir de intrare si verifica daca automatul il accepta sau nu. Automatul D are o stare initiala s0 si un set de stari de acceptare F. Sirul se termina cu un simbol special eof. 1. Dintr-o stare de acceptare nu pleaca nici o tranzitie. se observa ca va parcurge secventa de stari 012123. s = s0 c = caracterul_urmator cit timp c =/ eof executa s = move(s.

S = a = cit S a = ?-inchidere({s0}) caracterul_urmator timp a =/ eof executa = ?-inchidere(move(S. Fie N numarul de stari pentru AFN.a)) = caracterul_urmator daca S n F =/ O atunci rezultat "DA" altfel rezultat "NU" = Algoritmul poate sa fie implementat eficient utilizind doua liste si un vector indexat cu starile automatului finit nedeterminist. Deoarece in lista pot sa fie memorate maximum N stari. Algoritmul de simulare se aseamana cu cel utilizat pentru constructia unui automat finit determinist echivalent cu automatul N. respectiv "NU" daca N nu accepta x. atunci raspunsul este "DA" altfel raspunsul este "NU". Automatul N are o stare initiala s0 si o multime de stari de acceptare F. Utilizind algoritmul de calcul al starilor urmatoare pentru ?tranzitii se calculeaza setul ?-inchidere pentru o stare data. Dupa ce s-a terminat calculul ?-inchiderii pentru o stare se face schimbarea rolului celor doua liste. Sirul se termina cu un simbol special eof. fiecare stare poate sa produca cel mult doua stari noi.Intrare un AFN (N) si un sir de intrare x. Intr-o lista se pastreaza setul starilor curente ale automatului. in cealalta setul starilor urmatoare. calculul starii urmatoare se poate face intr-un timp proportional N . In momentul in care s-a ajuns la sfirsitul sirului (s-a ajuns la eof) daca in setul starilor curente este inclusa si o stare de acceptare. Vectorul este utilizat pentru a asigura functionarea listei ca o multime in sensul ca daca o stare este continuta in lista atunci ea nu trebuie sa mai poata fi adaugata. Sa reluam de exemplu automatul : ? ---------------+ / / +-+ +-+ / ? a / / --> 2 -> 3 \ ? / / \ +-+ +-+ / +-+ +-+ +-+ +-+ +-+ +-+ +--+ ? / ? a b b ---> 0 -> 1 6 -> 7 -> 8 -> 9 -> 10 \ / -+-+ +-+ \ +-+ +-+ / +-+ +-+ +-+ +-+ +--+ \ \ ? b /? /\ \ --> 4 -> 5 / / . Deoarece fiecare stare are cel mult doua tranzitii. diferentele constau in faptul ca pentru fiecare multime de stari S in care poate sa ajunga automatul pentru un prefix al sirului x se considera pentru construirea setului S' de stari urmatoare numai simbolul curent din sirul x. Raspuns "DA" daca N accepta x. Deci timpul necesar pentru simularea AFN pentru sirul de intrare x va fi proportional cu N x x .

7.9} Se observa ca s-a ajuns la multimea {1.2.8}) = {1. Sa consideram de .6.6.4.6. Simularea AFD se face intr-un timp proportional cu x indiferent de numarul de stari ale AFD. Aceasta abordare este avantajoasa daca este necesara verificarea a mai multor siruri de lungime mare pentru o aceasi expresie regulata (vezi de exemplu situatia in care un editor de texte are o functie de cautare pentru un subsir de o forma generala data). Algoritmul de simulare pentru AFN are un numar de operatii proportional cu S x x deci cu r x x (unde x reprezinta lungimea sirului x).1.7.7} lista 2 ?-i({3. Probleme de implementare pentru automatele finite deterministe si nedeterministe In general automatele finite sint utilizate pentru implementarea analizoarelor lexicale.5.1. Evolutia celor doua liste va fi urmatoarea : lista 1 a -----------> ?-i({0}) = {0. Se poate construi automatul finit nedeterminist (AFN) corespunzator expresiei regulate. iar numarul de tranzitii pentru fiecare stare este 2 (conform constructiei). Din cele prezentate anterior se observa ca dindu-se o expresie regulata r si un sir de intrare x exista doua metode pentru a verifica daca x E L(r).9} care nu contine o stare de acceptare deci sirul x nu este acceptat de catre automat.4.8} b <-----------?-i({5. 1. deci memoria maxima necesara pentru tabela de tranzitii este proportionala cu r .9}) = {1.\ \ +-+ +-+ / \ ? / -------------------- / Acest AFN accepta expresia regulata (a b)*abb. Pe de alta parte exista expresii regulate pentru care AFD-ul necesita un spatiu de memorie exponential in numarul de simboli si operatori din expresia regulata.4.2.3.2. Numarul maxim de stari pentru AFN este de maximum 2 x r .7. Daca expresia regulata r contine r simboli atunci aceasta constructie se face intr-un timp proportional cu r . Daca x nu este foarte mare solutia este acceptabila.5.3.2. O alta abordare posibila este construirea automatului finit determinist (AFD) corespunzator automatului finit nedeterminist construit pornind dela expresia regulata. Specificarea atomilor lexicali se face de obicei sub forma de expresie regulata (mai rar ca gramatica regulata). Din acest motiv este interesant sa discutam modul in care pornind de la o expresie regulata putem sa ajungem la un program care sa realizeze "executia" sau altfel spus simularea automatului finit corespunzator.4. Sa consideram de exemplu sirul de intrare x = ab.6.

i) Fie w E T* spunem ca w separa starile s. O alta abordare este de a utiliza un AFD. Ori de cite ori este necesara o tranzitie se face o cautare in memoria asociativa. deci sint necesare cel putin 2 ** n stari (pentru a codifica toate combinatiile de caractere a si b de lungime n).w).w) E/ F sau m^(t. S-F si {d}.i) este nedefinita in automatul initial vom considera ca m(s. pentru care Q > 1. Initial. m(d. Ideea construirii automatului redus echivalent unui automat dat este de fapt problema construirii partitilor induse de o relatie de echivalenta.i) = d. fara a construi intreaga tabela de tranzitii.q2 E Q. Concentrind rezultatele se obtine urmatoarea tabela : AFN AFD ---------------------------------------------------------------complexitate constructie O( r ) O( r x T ) ---------------------------------------------------------------memorie ocupata O( r ) O(c ** r ) ---------------------------------------------------------------complexitate simulare O( r x x ) O( x ) ---------------------------------------------------------------1. In cele ce urmeaza consideram ca automatul finit are functia de tranzitie definita pentru intreg domeniul S X T.i E T. (V.. astfel incit exista un simbol a pe pozitia n de la sfirsitul sirului.exemplu expresia : (a b)*a(a b)(a b). a) fac parte din elemente diferite din P inseamna ca starile succesoare starilor q1 si q2 nu fac parte din aceeasi multime a partitiei. etc.(a b) care reprezinta un sir de simboli a si b si care se termina cu (n -1) simboli (a b). Ideea este de a determina o tranzitie numai daca este necesara. {d}}. se parcurg simbolii de intrare. consideram ca multimea S este impartita in F.i) E S x T pentru care m(s. (V.i) = d. O data calculata o tranzitie aceasta este memorata intr-o memorie asociativa.wi) = m(m^(s. In continuare pentru o multime de stari Q E P. a) si m(q2. m(q1.s E S)(V-w E T*)(V-i E I)(m^(s. Fie P = { S .3. pentru V-s E S. m^ : S x T* --> S in modul urmator : 1. F. ?) = s) 2.s E S)(m^(s.1. Minimizarea numarului de stari pentru AFD Se poate demonstra ca fiind data o multime regulata exista un unic automat finit determinist cu numar minim de stari care accepta limbajul generat de multimea respectiva.w) E F si m^(t. Daca pentru un simbol a E T si starile q1.i) nu este definita consideram o extindere a automatului pentru care adaugam o stare d. Daca exista combinatii (s. Corespunzator S va fi impartit in 3 multimi.7. Sirul reprezentat de aceasta expresie regulata este format din cel putin n simboli a si b. Se observa ca un AFD pentru recunoasterea acestei expresii trebuie sa memoreze ultimele n caractere.F.. q2 E/ F exista o secventa de intrare care sa le separe. V-i E T pentru care m(s.w) E/ F Un automat este redus daca si numai daca pentru oricare doua stari q1. Algoritmul corespunzator este: .w) E F si m^(s.t E S daca si numai daca m^(s. Pentru V. Construim o extensie a functiei m.

m.{Q} Q = Q .a] goto_next = tranz_AFD[next. Sa consideram urmatorul exemplu : b --\ / +---+ b al se un n . Q ne marcat marcheaza Q new = O/ daca Q > 1 atunci alege first E Q Q' = Q .new P = P U {Q} U {new} = pina nu mai exista Q E P ne marcat pina P = P' Algoritmul utilizat nu este optim din punct de vedere timpului de executie. Exista algoritm pentru care numarul de operatii este proportional cu log n. S-F.Intrare Un automat finit determinist (S.{a} goto_first = tranz_AFD[first. {d}} repeta P' = P repeta alege Q E P. Descrierea algoritmului este: P = {F.{first} cit timp Q' =/ O/ executa alege next E Q' Q' = Q' .F) Iesire Multimea multimilor de stari echivalente din AFD.s0. a] daca goto_next si goto_first sint in elemente (multimi) diferite din P atunci new = new U {next} se_imparte = true = = = daca new =/ O/ atunci P = P .T. La fiecare pas multimea de stari Q imparte in cel mult doua noi multimi : new si Q\new.{next} se_imparte = false T' = T cit timp T' =/ O/ and not se_imparte executa alege a E T' T' = T' .

b) E/ Q.+-<--------+ a a +--<--------------------+ Initial P = {{0. an banda de intrare de tip (read only) +--------------\ cap de citire \ +---------+ unitate +----+ de --. Se observa ca P =/ P'.. m(2.b). Pentru next = 2.--> 2 <---------------------+ / ++---+ /a +---+ start / +---+ +---+ +------+ ------. memoria stiva ---zn +----+ b .2.1.2}. m(0.3}.b) E Q.3}. m(0. b) E Q. Q = {0. Rezulta P = {{0. Pentru Q = {0.b). {3}. {4}}. m(2.a) E Q. Se obtine automatul finit determinist cu numar minim de stari: b b ---------<--------------------+ \/ / +---+ / start / +---+ +---+ +-----+ ------> 02 a b b +---+ -----> 1 ------> 3 -----> 4 +---+ +---+ +---+ +---+ +-----+ /\ a -.b) E Q.1.a).0 a \/ b b +----+ -----> 1 ------> 3 -----> 4 +---+ +----+ +---+ +---+ +------+ /\ a -.1..+-<--------+ a a +--<--------------------+ 1.b) E Q dar m(3.1. a) E Q. deci new = {3}. next = 1. m(0.2} se obtine m(0. m(0.2}.z1 control ---+---------+ z2 ---. m(2. S-a obtinut P = {{0. {1}. m(1. Continuind pentru next = 3.a) E {1}. Se obtine m(0.2.. m(2.. {4}}.2}. m(0. {3}.b) E Q. Urmeaza Q = {0. m(1.a). {4}}. a) EQ.b) E/ Q. Fie first = 0. m(0.b) E Q dar de aceasta data m(1. Automate cu stiva(pushdown) Un astfel de automat are o memorie organizata ca o stiva : +--------------a0 a1 .4.

Un automat pushdown (PDA) este un obiect matematic definit in modul urmator P = (S,T,Z,m,q0,z0,F) unde : S - este o multime finita de simboli ce reprezinta starile posibile pentru unitatea de control a automatului; T - este multimea finita a simbolilor de intrare; Z - este multimea finita a simbolilor utilizati pentru stiva; m - este o functie, m : S x (T U {?}) x Z --> P(S x Z*) este functia care descrie modul in care se obtine starea urmatoare si informatia care se introduce in stiva pentru o combinatie stare, intrare, continut stiva data; q0 E S este starea initiala a unitatii de control; z0 E Z este simbolul aflat in virful stivei in starea initiala; F C_ S reprezinta multimea finita a starilor finale. O configuratie de stare a automatului este un triplet (q,w,a) E S x T* x Z* unde : q - reprezinta starea unitatii de control; w - reprezinta partea din banda de intrare care nu a fost inca citita. Daca w = ? inseamna ca s-a ajuns la sfirsitul benzii de intrare; a - reprezinta continutul stivei. O tranzitie a automatului este reprezentata prin relatia asupra multimii configuratiilor automatului definita in modul urmator : (q,aw,za) - (q',w,Ba) unde (q',B) E m(q,a,z), q E S, a E T U {?}, w E T*, z E Z, a E Z*. Daca a =/ ? inseamna ca, daca unitatea de control este in starea q, capul de citire este pe simbolul a iar simbolul din virful stivei este z atunci automatul poate sa-si schimbe configuratia in modul urmator : starea unitatii de control devine q', capul de citire se deplaseaza cu o pozitie la dreapta iar simbolul din virful stivei se inlocuieste cu B. Daca a = ? inseamna ca avem o ?-tranzitie pentru care simbolul aflat in dreptul capului de citire pe banda de intrare nu conteaza (capul de citire nu se va deplasa), insa starea unitatii de control si continutul memoriei se pot modifica. O astfel de tranzitie poate sa aibe loc si dupa ce s-a parcurs intreaga banda de intrare. Daca se ajunge intr-o configuratie pentru care stiva este goala nu se mai pot executa tranzitii. Relatia - se poate generaliza la -i, -+, -*, intr-o maniera similara relatiei de derivare pentru forme propozitionale. O configuratie initiala pentru un automat push down este o configuratie de forma (q0,w,z0) unde w E T*. O configuratie finala este o configuratie de forma (q,?,a) cu q E F, a E Z*. Spunem ca un sir w este acceptat de un automat push down prin stari finale daca (q0,w,z0) -* (q,?,a) pentru q E F si a E Z*. Limbajul acceptat de un automat pushdown P in acest mod se noteaza cu L(P). Sa consideram de exemplu automatul push down care accepta 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)} Z de 1 va

Pentru toate celelalte elemente (s, a, z) E S x (T U {?}) x care nu sint descrise de regulile de mai sus, m(s, a, z) = O/. Se observa ca automatul copiaza toate zerourile de pe banda intrare in stiva si apoi descarca stiva pentru fiecare simbol intilnit la intrare. De exemplu pentru sirul 0011, automatul executa urmatoarea secventa de tranzitii : (q0,0011,z) (q1,011,0z) (q1,11,00z) (q2,1,0z) (q2,?,z) (q0,?,z)

Pentru sirul de intrare 011 care nu apartine limbajului evolutia va fi : (q0,011,z) (q1,11,0z) (q2,1,z) (q2,1,z) (q0,1,z)

Se observa ca desi s-a ajuns intr-o stare finala nu s-a ajuns la sfirsitul sirului de intrare deci sirul nu a fost acceptat. Pentru sirul de intrare 001, evolutia este : (q0,001,z) - (q1,01,0z) - (q1,1,00z) - (q2,?,0z)

In acest caz s-a ajuns la sfirsitul sirului dar starea in care se gaseste automatul nu este finala deci nici aces sir nu este acceptat. Pentru a demonstra ca L(P) = {0n1n} trebuie sa aratam ca {0n1n} C L(P) si L(P) C {0n1n}. In general se pot face urmatoarele observatii : (q0,0,z) (q1,0i,0z) (q1,1,0i+1z) (q2,1i,0iz) (q2,?,z) - (q1,?,0z) -i (q1,?,0i+1z) - (q2,?,0iz) -i (q2,?,z) - (q0,?,z)

Rezulta ca pentru sirul 0n1n, n > 1 se obtine : (q0,0n1n,z) -2-n-+-1 (q0,?,z), n > 1 (q0,?,z) -0- (q0,?,z) Deci {0n1n} C_ L(P). Trebuie sa aratam ca si L(P) C_ {0n1n} . Se observa ca pentru a accepta un sir, P trece in mod obligatoriu prin succesiunea de stari q0,q1,q2,q0 daca n > 0. Daca (q0,w,z) -i (q1,?,a), i > 1

inseamna ca w = 0i si a = 0iz. Daca (q2,w,a) -i (q2,?,B) inseamna ca w = 1i si a = 0iB. Daca (q1,w,a) - (q2,?,B) inseamna ca w = 1 si a = 0B. Daca (q2,w,z) -* (q0,?,z) inseamna ca w = ?. Deci daca (q0,w,z) -i (q0,?,z) atunci fie w = ? si i = 0 fie w = 0n1n, i = 2n + 1. Deci L(P) C_ {0n1n} . Sa consideram si automatul care accepta limbajul L = {wwR w E {a,b}+}, P = ({q0,q1,q2},{a,b},{z,a,b},m,q0,z,{q2}) unde : m(q0,a,z) m(q0,b,z) m(q0,a,a) m(q0,a,b) m(q0,b,a) m(q0,b,b) m(q1,a,a) m(q1,b,b) m(q1,?,z) = = = = = = = = = {(q0,az)} {(q0,bz)} {(q0,aa),(q1,?)} {(q0,ab)} {(q0,ba)} {(q0,bb),(q1,?)} {(q1,?)} {(q1,?)} {(q2,?)}

Functionarea automatului pentru recunoasterea unui sir parcurge trei etape. In prima etapa se copiaza in stiva sirul w, apoi stiva se descarca pentru wR. Ultima etapa recunoaste sfirsitul sirului de intrare in conditiile descarcarii complete a stivei. Prima etapa este caracterizata de starea q0, urmatoarea de q1, q2 fiind starea finala. In prima etapa daca simbolul curent de pe banda de intrare nu coincide cu simbolul din virful stivei atunci nu s-a ajuns la sfirsitul sirului w si deci simbolul aflat sub capul de citire este copiat in virful stivei. Daca insa simbolul curent de pe banda de intrare coincide cu simbolul din virful stivei atunci fie s-a ajuns la sfirsitul sirului w si incepe wR si deci trebuie sa inceapa descarcarea stivei fie nu s-a ajuns la sfirsitul sirului w si atunci simbolul aflat sub capul de citire trebuie sa fie copiat in virful stivei. Din cele prezentate anterior rezulta caracterul nedeterminist al automatului. Sa consideram de exemplu secventa de miscari pentru sirul abba. (1) (q0,abba,z) (q0,bba,az) (q0,ba,baz) (q0,a,bbaz) (q0,?,abbaz)

Se observa ca pentru aceasta secventa de tranzitii nu se ajunge intr-o stare finala. Automatul fiind nedeterminist trebuie sa cercetam insa toate secventele de tranzitii posibile : (2) (q0,abba,z) (q0,bba,az) (q0,ba,baz) (q1,a,az) (q1,?,z) (q2,?,?)

Rezulta ca automatul ajunge in starea q2 deci accepta sirul abba. Fie P = (S, T, Z, m, q0, z0, F) un automat pushdown. Spunem ca un sir w E T* este acceptat de P prin stiva goala daca (q0, w, z0) -+ (q, ?, ?) pentru V- q E S. Fie Le(P) multimea sirurilor acceptate de P prin stiva goala. Se poate demonstra urmatorul rezultat. Daca L(P) este limbajul acceptat de automatul P prin stari finale atunci se poate construi un automat pushdown P' astfel incit L(P) = Le(P').

)}.b.T. q'.w.(.z') = {(q0. a.a)} {(q. y1 y2 .w.w.?.(qe.P. Rezulta deci ca L(G) = L(R). {a.F) m(q. m'(q'. m.T)} {(q.. Fie G = (N.b) = = = = {(q. (qe. t E Z*. P..z) = {(qe. simbol care nu poate sa fie scos din stiva decit in starea qe.E+T).z0z') -n (q.a.(q.?) cu yr = z' daca si numai daca (q0.z0z')}.O) unde m este definita in modul urmator : m(q. o) unde functia m' este definita in modul urmator : 1.(q0. N U T. Sa consideram de exemplu o secventa pentru a + a * a. Dindu-se o gramatica independenta de context sa construim automatul care accepta limbajul generat de aceasta gramatica.n > 1.?.T*F).*. Se observa ca automatul astfel construit va accepta limbajul prin stiva goala.?). ?) E m'(q.+. m'(qe. Daca A --> a E P atunci (q.E) unde P = {E --> E + T T.. P' poate continua simularea sau intra intr-o stare speciala qe in care se goleste stiva (qe E/ S). yr-1) pentru q E F si y1 y2 . Deci Le(P') = L(P).?.(q.Automatul P' va simula functionarea automatului P.?.A) -n (q. adica dindu-se un automat push down si limbajul acceptat de acesta prin stiva goala se poate construi un automat push down care accepta acelasi limbaj prin stari finale. T.?)} pentru orice a E T. yr) . Altfel spus exista o derivare S =+=> w daca si numai daca (q.?.?.*.T) m(q. Se poate arata ca A =k=> w daca si numai daca (q.)}.z0) -n(q. O) unde m este construita conform urmatoarelor reguli : 1.?.?. T.. 2.?. F --> (E) a}.F)} {(q.?) k.?.z E Z U {z'}. S. 4. Z U {z'}. a E T U {?}. Ori de cite ori P intra intr-o stare finala. pentru V.F.a) = {(q.(E)).. {a.(.y1 y2 . a.{E.+.+.?...w.T. T --> T * F F. Limbajele acceptate de automatele pushdown sint limbajele ce fi descrise de gramatici independente de context. z).?.*.m.?)} Se observa ca : (q'. Aplicind constructia propusa rezulta R = ({q}.E) m(q. t) E m(q. daca (r. yr-1 E Z*. Se poate demonstra si rezultatul invers. m'. pentru V. yr) -r---1 (qe. 3. F}.(q.?)} cu b E {a.q'}. q E S. z E Z.a) E m(q. q. se obtine automatul pushdown R = ({q}. Fie P' = (S U {qe.E.)}.S).z') .y2 .z).a. m(q.+. t) E m'(q. . pentru r.?. z'.(.A) 2. Pentru astfel de situatii se considera un simbol special pentru initializarea stivei.)}. Se poate insa observa ca P poate sa execute o secventa de miscari pentru un sir de intrare w care sa permita golirea stivei fara ca sirul sa fie acceptat de catre automatul P (pentru P nu conteaza decit ajungerea intr-o stare finala).q E F si z E Z..S) -+ (q. z) atunci (r.q. Sa construim de exemplu automatul care recunoaste gramatica expresiilor aritmetice G = ({E.(. T. P' isi initializeaza stiva cu z0z' (z'reprezinta simbolul de initializare al stivei pentru P').w.

T * a * a.?) = {(q.Z.a)} m(q.b. + a * a. (q. F) a. E / \ / \ E + T / \ / \ T T * F F F a a Acest gen de construire de secvente de derivare si deci automatele pushdown de tipul celor definite sint utilizate in analiza sintactica top down sau predictiva. {a. (q. (q.T. (q. (q.b}*}.F) pentru care m : S x (T U {?}) x Z* --> P(S x Z*). Fie P = ({q. Sa consideram de exemplu automatul care accepta limbajul L = {wwR w E {a. Din acest motiv se spune ca am utilizat o derivare stinga. Consideram pentru acest tip de automat acceptarea prin stari finale. m.b.b)} m(q.b}. ?). (q. a + a * a. a + a * a.(q.S)} a .z. (q.S.q0. a + a * a. (q. + a * a.m.?. (q.?) = {(q. a + a * a. E + T + F + a + T) F) F) F) T) T) T) T) In reprezentarea tranzitiilor virful stivei a fost reprezentat in stinga. dar si in acest caz se poate construi un automat echivalent care sa faca acceptarea prin stiva goala.?) = {(q. F * a * a. (q. Se observa ca aceasta secventa de tranzitii simuleaza secventa urmatoare de derivari de forme propozitionale : E ==> E + T ==> T + T ==> F + T ==> a + T ==> a + T * F ==> a + F * F ==> a + a * F ==> a + a * a. T) a * a. {a. (q. Un tip special de automat cu stiva il reprezinta automatul pushdown extins E = (S. a * * a. (q. Se observa ca in acest caz din stiva se considera nu numai simbolul din virful stivei ci un sir de simboli aflat in virful stivei.{p}) unde functia m este definita in modul urmator : m(q. E ) - (q. a + a * a.z}.a.p}.z0. Secventa de derivari anterioare poate sa fie reprezentata prin urmatorul arbore de derivare. a) ?. * F) a.q. Se observa ca in aceasta secventa s-a inlocuit intodeauna cel mai din stinga neterminal.

S)} m(q. Din acest motiv se spune ca s-a construit o derivare dreapta.?.?. Daca B este cel mai din stinga astfel de sir atunci spunem ca B este capatul sirului aBw. Se poate demonstra ca pentru orice automat pushdown extins E.a.bSb) = {(q.baa.Saz) (q.S)} m(q. c.?)} De exemplu pentru secventa de intrare aabbaa rezulta urmatoarea secventa de tranzitii : (q.S).?. Pentru sirul obtinut abb este capat deoarece aBbbd este o forma propozitionala anterioara din derivarea dreapta.aSa) = {(q. Sa revenim la problema acceptarii limbajelor independente de context de catre automate pushdown si sa consideram din nou exemplul expresiilor aritmetice.aSaz) (q.{a.?.aSaaz) (q. Sa consideram de exemplu gramatica: G = ({S. d}. {S--> Ac Bd.az) (q. in timp ce ab nu este deoarece aAbbbd nu este o forma propozitionala care poate sa apara dintr-o derivare dreapta.aaz) (q.abbaa.aa.Saaz) (q.Sz) (p.aa.bbaa.T.aabbaa.?) Se observa ca datorita tranzitiei m(q.Sbaaz) (q. A --> aAb ab. Fie gramatica G = (N.?) = {(q.a. Deci un capat (handle) pentru o derivare dreapta este orice sir care este partea dreapta a unei productii si poate sa fie inlocuit de neterminalul corespunzator intr-o forma propozitionala care a aparut dintr-o derivare dreapta obtinindu-se forma propozitionala anterioara din cadrul respectivei derivari dreapta. Aceasta gramatica genereaza limbajul {anbnc n > 1} U {anb2nd n > 1}.?. Pentru generarea sirului a + a * a putem sa consideram si urmatoarea secventa de derivari : E ==> E + T ==> E + T * F ==> E + T * a ==> E + F * a ==> ==> E + a * a => T + a * a ==> F + a * a ==> a + a * a. Sa consideram urmatoarea secventa de derivari S ==> Bd ==> aBbbd ==> aabbbbd.z) (q. A.Sz) = {(p.S)} si acest automat este nedeterminist.m(q. b. .P.S) o gramatica independenta de context sa presupunem ca S =*=> aAw ==> aBw =*=> xw.?. Se observa ca in aceasta secventa s-a inlocuit intodeauna cel mai din dreapta neterminal.?. Daca in fiecare derivare a fost inlocuit de fiecare data neterminalul cel mai din dreapta atunci se spune ca aBw se reduce stinga la aAw daca A--> B E P. B --> aBbb abb}.bSbaaz) (q.baaz) (q. B}. Considerind acest tip de derivari si parcurgindu-le in ordine inversa (de la sfirsit) se poate introduce notiunea de reducere stinga.baa. exista un automat pushdown P astfel incit L(E) = L(P).

Sa consideram din nou gramatica pentru expresii aritmetice si secventa de derivari dreapta : E ==> E + T ==> E + T * F ==> E + T * a ==> E + F * a ==> ==> E + a * a => T + a * a ==> F + a * a ==> a + a * a. Rezulta arborele de derivare : E / \ / \ E + T / \ / \ T T * F F F a a Daca analizam acest arbore se vede ca a (care reprezinta frunza celui mai din stinga subarbore) este un capat, daca se reduce se obtine arborele : E / \ / \ E + T / \ / \ T T * F F F a Continuind se ajunge la : E / \ / \ E + T / \ / \ T * F F a Urmatorul capat este a, etc. Se observa ca pentru a identifica un capat pentru o forma propozitionala obtinuta printr-o derivare dreapta se considera secventa frunzelor celui mai din stinga subarbore de adincime 1 (toate nodurile acestuia sint fie frunze fie noduri din care deriva frunze). De exemplu : a a a

a sau F sau T sau / T

T / \ \ * F dreapta ale derivare se = (N,T,P,S) sa opereze

pentru care a, F, T respectiv T * F reprezinta parti unor productii. Aceasta metoda de reducere a arborilor de numeste "handle pruning". Dindu-se o gramatica independenta de context G se poate construi un automat pushdown extins care conform metodei handle pruning in modul urmator : R = ({q,r},T,N U T U {$}, m, q, $, {r}) unde

1. m(q,a,?) = {(q,a)} pentru orice a E T. Se observa ca simbolii a E T sint copiati in stiva; 2. daca A --> a E P atunci (q,A) E m(q,?,a) 3. m(q,?,$S) = {(r,?)}. Sa construim utilizind aceasta tehnica automatul pushdown extins care accepta gramatica expresiilor aritmetice : R = ({q,r},{a,+,*,(,)},{a,+,*,(,),T,F,E,$},m,q,$,{r}) unde m(q,b,?) = {(q,b)}, pentru b E {a,+,*,(,)} m(q,?,E + T) = {(q,E)} m(q,?,T) = {(q,E)} m(q,?,T * F) = {(q,T)} m(q,?,F) = {(q,T)} m(q,?,(E)) = {(q,F)} m(q,?,a) = {(q,F)} m(q,?,$E) = {(r,?)} Find vorba de o derivare dreapta, virful stivei a fost figurat in dreapta. Se observa ca aceasta secventa de tranzitii este unica secventa ce duce la acceptarea sirului de intrare. Pentru sirul a + a * a, automatul R va executa urmatoarele tranzitii : (q, a + a * a, $) (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, (q, + a * a, $a) + a * a, $F) + a * a, $T) + a * a, $E) a * a, $E +) * a, $E + a) * a, $E + F) * a, $E + T) a, $E + T *) ?, $E + T * a) ?, $E + T * F) ?, $E + T) ?, $E) ?, ?)

Automatele push down construite dupa modelul prezentat anterior vor fi utilizate in analiza sintactica de tip bottom-up. Un automat push down este determinist daca pentru orice configuratie exista cel mult o singura tranzitie urmatoare. Mai

precis un automat push down PD = (S, T, Z, m, q0, z0, F) este determinist daca pentru orice (q, a, z) E S x (T U {?}) x Z sint indeplinite urmatoarele conditii : 1. m(q, a, z) <= 1, 2. daca m(q, ?, z) =/ O/ atunci m(q,a,z) = O/ pentru V- a E T Avind in vedere echivalenta dintre un automat push down si limbajele independente de context, vom spune ca un limbaj independent de context este determinist daca este acceptat de un automat push down determinist. Vom modifica putin conditia de acceptare, considerind ca un limbaj independent de context este determinist daca exista un automat pushdown determinist care accepta limbajul L$. Simbolul $ este un simbol care nu apare in alfabetul peste care este definit limbajul L. Se observa ca utilizarea acestui simbol care apare concatenat cu fiecare sir din L indica de fapt posibilitatea automatului push down de a recunoaste sfirsitul sirului. In acest mod s-a extins de fapt clasa limbajelor independente de context deterministe. Se pune intrebarea daca orice limbaj independent de context este determinist. sa consideram de exemplu limbajul : L0 = {am1bam2b ... amn n >= 2, m1, ..., mn >= 0, mi=/mj pentru un i si un j}

Evident un automat push down care accepta acest limbaj trebuie sa ghiceasca ce grup de a-uri trebuie sa fie comparat cu alt grup de a-uri, pentru a lua decizia cind sa faca o memorare in stiva si cind sa incerce sa descarce stiva. Intutitiv o astfel de operatie nu se poate realiza cu un dispozitiv determinist. Propozitie. Clasa limbajelor acceptate de automate push down nedeterministe este mai larga decit clasa limbajelor acceptate de automate push down deterministe. 1.5. Masina Turing O masina Turing este un acceptor care "stie" sa scrie pe banda de intrare care devine in acest mod memorie auxiliara. Masina Turing a fost definita de catre matematicianul englez Alan Turing (1912 - 1954) in anul 1930. Cind a inventat masina care ii poarta numele, Turing era interesat nu de calculatoare ci de posibilitatea rezolvari problemelor matematice utilizind mijloace automate. Adica, poate sa fie rezolvata orice problema matematica utilizind niste reguli elementare de prelucrare a sirurilor ?. +---------------------------banda de intrare +---------------------------^ cap de citire / scriere +---------+ unitate de control +---------+ Unitatea de control comanda executia miscarilor. O miscare este formata din :

In cele ce urmeaza vom indica simbolul blanc cu ajutorul caracterului #. (q0. s E S este starea initiala a masinii Turing. noua stare find q1. Deoarece masina Turing este in stare sa scrie pe banda de intrare. Se observa ca pentru aceasta stare initiala.stabilirea starii urmatoare pentru unitatea de control. m(q1.a) = (p. m(q0. Se continua evolutia intr-o maniera similara pina cind in starea q0 capul de citire se gaseste pe un caracter . unde m(q0. Banda de intrare este marginita la stinga si infinita la dreapta.. m este functia de tranzitie m : S x T -> (S U {h}) x (T U {L. Se observa ca asa cum este definita masina Turing functionarea sa este determinista. a E T si m(q. Se numeste masina Turing obiectul matematic : MT = (S. avind a sub capul de citire masina trece in starea p. R}. Exista insa o stare speciala numita stare de oprire (de halt) pe care o vom nota in continuare cu h. De asemenea vom utiliza caracterele L si respectiv R pentru a indica o deplasare la stinga respectiv la dreapta. {a. (q0. Sa consideram insa o definitie formala a notiunii de masina Turing.scrierea unui simbol pe banda de intrare sau executia unei deplasari cu o pozitie spre stinga sau spre dreapta. m(q1. q0). Dupa pozitia ocupata de sirul de intrare pe banda aceasta contine blancuri. Daca b E T atunci simbolul a va fi inlocuit cu b. Pentru q1. R}). Acceptarea sau neacceptarea unui sir poate sa fie indicata de continutul benzii cind se ajunge in starea de oprire. (h. ea este capabila sa lase un raspuns inscris pe banda. #}. . Daca q E S. In acest ultim caz se spune ca masina s-a agatat (a ajuns intr-o stare de agatare . deci nu mai este nevoie de notiunea de stare finala. a) #) a) #) = = = = (q1. primul simbol a este inlocuit cu #. T este alfabetul finit de intrare care contine simbolul # dar nu contine simbolii L si R. Incetarea functionarii masinii Turing se face daca se ajunge in starea h (cind masina se opreste) sau daca se incearca deplasarea la stinga dincolo de capatul din stinga al benzii.b) inseamna ca fiind in starea q. h E/ S. m. daca sub capul de citire se gaseste un caracter # atunci se va face o deplasare la dreapta starea devenind q0.hanging state). altfel capul se va deplasa cu o pozitie la stinga sau la dreapta in functie de valoarea simbolului b E {L. Asa cum s-a construit definitia ea reprezinta o masina Turing standard. m. Sa consideram de exemplu MT = ({q0. #) #) a) R) Sa consideram ca pe banda de intrare se gaseste sirul aaa si ca pozitia capului este pe primul caracter din sir. q1}. s) unde S este o multime finita a starilor masinii Turing. T.

a1. Daca nu exista un astfel de simbol masina inceteaza sa functioneze cind ajunge la capatul din stinga a benzii. R} astfel incit m(q1. Deci o configuratie este de forma (q.w1. u1) nu are o configuratie urmatoare. aiB).{#}) U {?}). Sa consideram si urmatorul exemplu MT = ({q0}. deoarece sirul de intrare este finit in timp ce banda de intrare este infinita la dreapta putem sa consideram ca sirul se termina cu un caracter care nu este # (oricum in continuare pe banda apar numai caractere #). simbolul aflat sub capul de citire / scriere ( i E T) si sirul aflat la dreapta capului de citire / scriere ( B E (T* (T . a2 = b. 2.w2.#. . In acest moment se ajunge in starea h si masina se opreste.a2. L) m(q0. in acest caz se spune ca (q1. subliniind simbolul pe care se gaseste capul de citire / scriere. u1) este o configuratie de agatare. b = L. Pentru simplificare o configuratie se poate reprezenta si sub forma (q. a2. Asupra configuratilor se poate defini o relatie de tranzitie . #) = (h. u1) si (q2. q0). u2) doua configuratii.u2) daca si numai daca exista b E T U {L. a1. w1. a1. a1) = (q2. O configuratie pentru o masina Turing este un element din multimea : (S U {h}) x T* x T x (T* (T . a. In al doilea caz este descrisa o miscare la stinga respectiv in cazul 3 se descrie o miscare la dreapta.(q2. w1 = w2. b) si este indeplinita una dintre urmatoarele conditii : 1. w1 = w2a2 daca a1 =/ # sau u1 =/ ? atunci u2 = a1 u1 altfel u2 = ? /* capul de citire / scriere se gaseste dupa sirul de intrare */ 3. B).{#}) U {?}) Elementele unei configuratii sint . La gasirea acestui simbol se trece in starea h. a1. Se observa ca.starea curenta q E (S U {h}). Fie (q1. masina find intr-o stare de agatare (hanging state). b = R.u1) . sirul aflat pe banda de intrare la stinga capului de citire / scriere (a E T*).in modul urmator. w1. m. u1 = u2. #) In acest caz masina cauta primul simbol # la stinga pozitiei din care pleaca capul de citire / scriere. w2. Atunci (q1. i. Rezulta ca evolutia masinii duce la stergerea sirului de a-uri inscris pe banda. {a. a) = (q0. w1. #}. Daca b = L si w1 = ? atunci (q1. w2 = w1a1 daca u1 = ? atunci u2 = ? a2 = # altfel u1 = a2 u2 In cazul 1 se face inlocuirea simbolului curent de pe banda de intrare (a) cu b. b E T. unde m(q0.

cn astfel incit n >= 0 si c0 . m(q1. (q0. L) L) L) b) a) R) R) R) #) Sa consideram evolutia pentru sirul de intrare aab. (q2. Adica utilizind un alfabet I care contine un singur simbol. Spunem ca MT = (S. m(q2.Pentru relatia . #w#) -* (h. Daca T1 si T2 sint doua multimi alfabet care nu contin simbolul #. (q2.#u#). (q0.(q1. Un calcul efectuat de o masina Turing este o secventa de configuratii c0.cn... m(q2. (q1. (h..(q2. u E T2*.. q1. ##) . {a. ##) Functia calculata de aceasta masina Turing este functia de inlocuire a caracterului a cu caracterul b respectiv a caracterului b cu caracterul a. m. i diferit de #. #aab#) #aaa#) #aaa#) #aba#) #aba#) #bba#) #bba#) #bba#) #bba#) #bba#) #bba#) #bba#) Pentru sirul vid evolutia este : (q0. Daca pentru o functie f data exista o masina Turing care o calculeaza spunem ca functia f este Turing calculabila. m(q1. (q2. . (h.se poate considera inchiderea reflexiva si tranzitiva notata cu -*. Sa consideram de exemplu masina Turing MT = ({q0. (q0. #}.(h. Se poate considera ca o masina Turing stie sa evalueze functii definite pe siruri de simboli cu valori in siruri de simboli. T2 C_ T si pentru orice sir w E T1* daca u = f(w). (q1. (q1. (q0. . ##) . Se observa ca numarul 0 este reprezentat de sirul vid. a) b) #) a) b) #) a) b) #) = = = = = = = = = (q1. m(q0. reprezentarea unui numar natural n este data de sirul a E In. (q2.q0) unde functia m este definita in modul urmator : m(q0. #aab#) (q1. Se observa ca s-a considerat ca pozitia capului este dupa sfirsitul sirului de intrare atit la inceputul executiei cit si la sfirsitul acesteia. s) calculeaza f daca T1. atunci (s. m(q2. Se spune despre calcul ca are loc in n pasi. (q1.. m . b. (q1. Din domeniul sirurilor putem sa trecem in domeniul numerelor naturale considerind reprezentarea unara a numerelor naturale. (q0. In acest caz o functie f : N --> N este calculata de o masina Turing daca aceasta calculeaza f' : I* -> I* unde f'(a) = B cu a E In si B E If(n) pentru orice numar natural. ##) . . c1. T. q2}. (q2. (q2. (q0.c1 . (q2. m(q0. m(q1. Termenul de calcul nu a fost utilizat intimplator. sa consideram functia f : T1* -> T2*.

m . #ini#) ..(q4. {i.(q1. sintem ca la inceput s-a ajuns la stinga cu un numar imapar de a s-au sters zero sau un numar par de a raspuns D si oprire raspuns N si oprire au fost un numar impar de a daca w E L m(q3. q4. q0) cu m(q0. D.w E T* D / dL(w) = \ N daca w E/ L Se spune ca limbajul L este decidabil in sens Turing (Turing decidable) daca si numai daca functia dL este calculabila Turing.(q2. {a. MT = ({q0}..(q1. q6}. #D#) . q1. #in+1#) O masina Turing poate sa fie utilizata si ca acceptor de limbaj. ij E Inj. #iii#) . si B E If(n1. q0) unde m este o functie partiala definita in modul urmator : m(q0.}) * -> I* cu f'(a) = B pentru a un sir de forma i1. (q4. n numar natural. i) De exemplu (q0. Sa consideram de exemplu functia succesor f(n) = n + 1. #aa#) . In general : (q0. D si N. (q3. Daca dL este calculata de o masina Turing MT spunem ca MT decide L.(h. #aa#) . Sa consideram de exemplu limbajul L = {w E T* w mod 2 = 0. T = {a}} (limbajul sirurilor peste alfabetul T = {a} care au lungimea un numar par). 1 <= j <= k. #ii#) . ##) .. #aa#) . #) = (q6. #in#) . (q2. N} o functie definita in modul urmator . ##) . (q0. q3. #D#) Pentru un sir incorect se obtine : (q0. #a#) . ##) . i) = (h. #) D) N) #) = = = = (q5.(h.pentru V.(q0. D) R) R) N) Sa consideram evolutia masinii pentru un sir corect : (q0. ik . #a#) ..(q0. Si anume sa consideram un limbaj L definit asupra alfabetului T care nu contine simbolii #. #}. q2.(h. m(q5. m(q3. #aaa#) . #iii#)... m. m(q6.(q2. (h. N.. m(q2. #aa#) . Functia dL corespunzatoare poate sa fie calculata de urmatoarea masina Turing : MT = ({q0. q5. R) m(q4. #}. Fie dL : T* -> {D. L) #) R) L) #) pornim spre stinga se sterge un a s-au sters un numar par de a s-a sters un a se continua spre stinga s-au sters doi de a. m(q1. R) m(q0. #aaa#) .(q0. (h. m(q1.De la un singur argument functia f se poate extinde la mai multe argumente .(q5. m(q5.(q3. . #) a) #) #) a) = = = = = (q1. (q5.(q3.nk). i2. #) = (q0.f : Nk --> N pentru care corespunde f' : (I U {.(q1.

a) = (h.. ww2a2u2) -* (q3. Limbajele Turing decidabile sint si Turing acceptabile. ##) . ww2a2u2) si (q2. #N#) . w2a2u2) in (q3. Daca sint posibile evolutiile : (q1. w2a2u2) -* (q3. w1a1u1) -* (q2.(q2. Daca un astfel de caracter este gasit masina se opreste (deci accepta sirul). Sa consideram de exemplu o masina Turing M1 care "stie" sa functioneze primind un sir pe banda de intrare pornind .(q5. (i = 1. 1. #a#) .1. Compunerea masinilor Turing Pentru a evidentia "puterea" de calcul a masinilor Turing vom prezenta mecanismul prin care o masina Turing se poate construi pe baza unor masini Turing mai simple. b. #}. spunem ca limbajul L este Turing acceptabil daca exista o masina Turing care se opreste daca si numai daca w E L. Daca insa pe banda de intrare se gaseste un sir care nu apartine limbajului atunci masina va intra in starea de agatare dupa ce a ajuns la capatul din stinga al benzii. b}* w contine cel putin un simbol a} considerind masina Turing MT = ({q0}. Deoarece masina are o functionare determinista va rezulta aceasi evolutie si daca sirul w2a2u2 nu este la inceputul benzii de intrare. Fie limbajul : L = {w E {a. w3a3u3) masina nu poate sa ajunga pe banda de intrare pe un simbol aflat la stinga sirului w2 (intr-o astfel de situatie s-ar ajunge la marginea din stinga a benzii. #N#) Notiunea de acceptare este mai larga decit notiunea de decidabilitate in legatura cu limbajele. b) = (q0. L) m(q0. m. Rezulta ca este posibila si evolutia (q2. #a#) . Pe baza propozitiei anterioare putem sa realizam compunerea masinilor Turing intr-o maniera similara utilizarii subprogramelor. 3) configuratii ale acestei masini. deci s-ar intra in starea de agatare si deci nu s-ar mai ajunge in configuratia urmatoare). q0) cu m(q0. {a. 2. Propozitie Fie MT o masina Turing si fie (qi. ww3a3u3). ##) .(q6. Si anume daca L este un limbaj asupra alfabetului T.(q3. Reciproca nu este insa adevarata. In evolutia din (q2. ##) .(h. L) Se poate constata ca daca pe banda de intrare se gaseste un sir din limbaj atunci pornind din configuratia initiala se va face cautarea unui simbol a prin deplasare spre stinga. ww3a3u3) Justificare. w1a1u1) -* (q3. #) = (q0.5.(q1. a) m(q0. w3a3u3) atunci este posibila si evolutia : (q1.(q0. wiaiui).

O schema de masina Turing reprezinta o masina Turing M. exista anume ({q}.n este o functie partiala . Acelasi mod de inlantuire va avea loc si la oprirea (daca intervine) masinii M'. n : M x T -> M. m. Mk}. q) cu m(q. atunci dupa ce M1 primeste controlul nu va depasi limita stinga a sirului sau de intrare. T. Vom nota masini cu L si respectiv R. R). Pentru a simplifica notatiile va fi reprezentata de simbolul a. ea va reprezenta masina MT = (S. a) = M'. sint posibile T masini care scriu fiecare cite simbol din T in pozitia curenta a capului. a) este nedefinita. m. si). . a E T.M0 E M este masina initiala. . In mod formal acest gen de compunere de masini Turing poate sa fie descris in modul urmator.. Sa presupunem ca M1 nu poate sa intre intr-o stare de agatare. M0) este o schema de masina Turing . 0 <= i <= k. a E m(q. Daca M0 se opreste atunci Mpoate continua eventual functionarea conform altei masini din M.. Reprezentarea compunerii masinilor Turing se face intr-o maniera asemanatoare unei structuri de automat finit pentru care o stare este reprezentata de o masina Turing. in acest caz M. La oprirea unei masini Turing (intrarea acesteia in starea h) in functie de simbolul aflat sub capul de citire se va trece intr-o alta stare. in acest caz functionarea continua cu starea initiala a masinii M'. a) = (h. b E T. La oprire capul va fi plasat de asemenea dupa sirul care a rezultat pe banda de intrare. L) si VR = T. . adica se va initia functionarea unei alte masini Turing.se opreste. Intrarea intr-o stare a automatului corespunde cu initierea functionarii unei masini Turing. a). Wa doua masini care executa deplasari elementare. T.M este o multime finita de masini Turing care au toate un alfabet comun T si multimi de stari distincte.n(M0. n. . 2.. T. mi.. deci nu va modifica un sir care eventual a fost memorat inainte pe banda de intrare.cu capul de citire / scriere pozitionat dupa sir. Fie q0. k >= 0 astfel incit Mi = (Si. b) = (h. Functionarea acesteia incepe cu functionarea masinii M0. O schema de masina Turing este tripletul (M. 0 <= i <= k. m. M0) unde . m. Si VL = ({q}. Daca (M. a) = (h.. 1. Fie M = {M0. qk stari care nu apar in multimile Si. T. Ca masini de baza pornind de la care vom construi noi masini Turing vom considera citeva cu functionare elementara. Daca M0 se opreste cu capul de citire / scriere pe caracterul a atunci exista urmatoarele situatii : .compusa din masinile care formeaza multimea M. q). Aceste masini au un un alfabet de intrare T comun. s) unde . q) cu m(q. .n(M0. aceste un de T. Daca M1 este utilizat in cadrul unei alte masini Turing care printre alte actiuni pregateste si un sir de intrare pentru M1. In cele ce urmeaza consideram ca masinile Turing care se combina nu pot sa intre in starea de agatare si ca fiecare are starile sale proprii diferite de starile tuturor celorlalte masini Turing. O astfel masina este definita ca find Wa = ({q}. n.

m.. R# = ({q.m este definita in modul urmator a..S = S0 U . a =/ # m(q0. n. b). a) = (p. q). q0}. b) atunci (p. b). b. R). a) = M0 daca a =/ # n(M0. R). a E T m(q0. qk au fost introduse ca puncte de trecere de la o masina la alta. a) (0 <= i <= k. p =/ h atunci m(q.. #) este nedefinita In acest caz (M.a).. a E T si mi(q. a) = (q0. Daca o masina se opreste si este definita masina urmatoare se va trece in starea care face legatura cu masina urmatoare. U Sk U {q0. . 0 <= i <= k.b). a) este definita si de exemplu M' = p =/ h . a) Se observa ca masina se deplaseaza la dreapta pina la primul simbol #. a) = (q0. a) = mi(q. 0 <= i <= k.. M. Daca nu este definita masina urmatoare. Sa consideram de exemplu multimea M = {M0} cu M0 = R = ({q}. a E T) si mj(sj. Dintr-o stare de legatura se intra in functionarea masinii urmatoare pe baza simbolului curent de pe banda de intrare.fiecare masina Mi E M apare o singura data. daca n(Mi. .s = s0 . c. a) = \ (qj. a) = Mj (0 <= i <= k. M0) reprezinta o masina notata cu R#.. daca n(Mi.daca a E T si n(Mi. Din definitie rezulta ca fiecare masina functioneaza "normal" pina cind se opreste.. d.masina initiala (M0) este indicata prin semnul >. Definim functia n in modul urmator : n(M0. a E T) este nedefinit atunci m(qi. a E T si mi(q.b) / m(qi. b. q) unde m(q. c} putem sa reprezentam masina R# sub forma : a ---\ / / \/ / > R < b /\ \ / \ \ ---c In cele ce urmeaza vom reprezenta grafic compunerea masinilor Turing utilizind o serie de reguli : . . a) = (p. a) = (qi. daca q E Si.. T. daca q E Si.. a) = (h. b) atunci m(q. T. #) = (h. a) = (h. Daca T = {a. qk} .a) = (p. . MT se va opri. b) p = h Se observa ca starile noi q0.

# 2 > R -----------> R sau > R ----> R sau RR sau R indicind faptul ca se fac doua deplasari la dreapta indiferent de continutul benzii de intrare. In cele ce urmeaza utilizam urmatoarele notatii : R#. a. Se poate intimpla ca in M sa apara mai multe copii ale aceleiasi masini (fiecare cu starile ei proprii diferite de starile celorlalte). este masina care cauta primul simbol # la stinga R#-. cind il gaseste il copiaza la stinga pozitiei pe care l-a gasit.a) atunci va exista un arc de la Mi la M' etichetat cu a. De exemplu schema : a ---------/ b \ > R -----------> R \ c / ---------\ # / ------------ peste alfabetul T = {a.b. este masina care cauta primul simbol diferit de # la dreapta L#-. In acest caz fiecare dintre exemplare reprezinta o alta masina Turing deci va fi desenata separat. Deci masina care cauta simbolul # la dreapta poate sa fie reprezentat ca : / / > R < \ \ Urmatoarea schema / / > R < \ \ a =/ # La cauta mergind la dreapta un simbol diferit de #. este notat generic cu a si poate sa fie utilizat in continuare. si care este diferit de #. c. b. este masina care cauta primul simbol # la dreapta L#. #} poate sa fie reprezentata a. In reprezentarile grafice urmatoare vom utiliza o serie de simplificari. este masina care cauta primul simbol diferit de # la stinga Utilizind aceste masini "simple" sa construim o masina de copiere # a =/ # sau > R < \ \ / / _ # . Daca a E T.n(Mi.reprezinta orice simbol din T diferit de a. Se observa ca din notatia a =/ # rezulta ca simbolul gasit.c.

Se spune ca masina transforma sirul #w# in #w#w#.(q. #ab##abc#) x . #abc#) -* (q.#abc#abc#) R# In evolutia prezentata anterior starea nu conteaza asa ca a fost notata cu un simbol generic q. C nu functioneaza corect daca la pornire la dreapta capului de citire se gaseste un simbol diferit de #.(q.(q.##bc#) R# . #a#c#ab#) L# .(q.(q. Evolutia masinii trebuie sa fie (s.(q. ##bc#a#) .(q. #abc#) .(q.(q. ##bc#a#) x .##bc##) R# . Reprezentarea grafica pentru aceasta masina este : +-------------------------+ x =/ # 2 2 >L --->R ---------->#R xL x -----+ # # # # R # Sa urmarim evolutia masinii pentru continutul benzii #abc# (q.(q. #ab#abc#) L#L# .(q.(q. #abc#abc#) R . #ab##ab#) R#R# . #abc#a#) .C care functioneaza in modul urmator.(q. #a#c#ab#) x . #a#c#ab#) L# .#abc#abc#) x .(q. #w#w#).(q. #abc#ab#) x .(q.(q. Sa presupunem ca pe banda de intrare se gaseste un sir w care nu contine simboli # (eventual sirul poate sa fie si vid). #abc#ab#) R . Se observa ca daca C incepe sa functioneze cu un continut al benzii de forma #u#v#w# la sfirsitul executiei se obtine pe banda #u#v#w#w#.(q. Capul este pozitionat pe simbolul # care marcheaza sfirsitul sirului w. ##bc#) R # . Presupunem ca la stinga sirului de intrare se gaseste un singur simbol #. #a#c#a#) R# . #abc#) L# .(q.(q.(h. #abc#a#) x .(q. Similar se poate construi o masina SR care transforma sirul #w# in ##ww#. #ab##ab#) # . pe banda de intrare nu se mai gasesc simboli diferiti de # care sa nu faca parte din w.(q. ##bc#a#) L# L# . #w#) -* (h.(q.#abc#abc#) . Masina SL : +----------------+ x=/# >L ---> R -----> LxR ----+ # # L# transforma sirul #w# in w#. #a#c#a#) R# . . #a#c#a#) R # .(q.

se pune problema daca aceasta nu poate sa fie facuta mai "puternica": prin adaugarea unor extensii care sa o apropie eventual de un calculator real. a E T1 atunci si M2 se opreste pentru w.asupra configuratiilor. uav). Se poate demonstra ca adaugarea unor facilitati ca de exemplu : banda de intrare infinita la ambele capete. Propozitie.daca M1 nu se opreste pentru w atunci nici M2 nu se opreste pentru w. i = n-1. f poate sa fie calculata de urmatoarea masina: +--------------------+ x=/# >L -----> #R xL x ----+ # # # R # Pe parcursul functionarii masina transforma siruri de forma #x1 . nu se schimba nici clasa functiilor care pot sa fie calculate si nici a limbajelor acceptate sau decise. v E T1*. u) si w nu incepe cu un simbol # iar u nu se termina cu un simbol #..{#} cu f : T0* --> T0* astfel incit f(w) =wwR. 1... pentru orice w E (T1 . xnxn . m2. a.. In acest caz o configuratie este de forma (q. .Fie T0 = T .. Nu mai exista limitari referitoare la deplasarea la stinga si deci dispar notiunile de stare si respectiv de configuratie de agatare. . Exista o masina Turing standard M2 = (S2. Demonstratiile de echivalenta sint constructive realizinduse pentru ficare extensie construirea unei masini Turing standard capabila sa simuleze functionarea unei masini Turing avind extensia considerata. #uav). mai multe capete de citire / scriere. nu creste puterea de calcul oferita. v E T1*. #w#) -* (h. xi . Fie M1 = (S1.5.. adica (q2. a E T1 .. xi+1#. 0... q2) astfel incit.. q1) o masina Turing cu banda de intrare infinita la ambele capete.. adica (q1.. Schimbarea definitiei formale pentru acest model de masina Turing intervine in modul in care se defineste notiunea de configuratie si relatia . xn# in #x1 . Pentru i = 0 se ajunge la #x1 . w. T2.. x1#.. w#) -* (h. Sa consideram de exemplu o masina Turing care are o banda infinita la ambele capete. mai multe benzi de intrare.2. xnxnxn-1 .{#})* sint indeplinite urmatoarele conditii : . Adica.. u. u. o banda de intrare organizata in doua sau mai multe dimensiuni (eventual o memorie asa cum apare la calculatoare). Extensii pentru masini Turing Avind in vedere simplitatea deosebita a functionarii unei masini Turing standard.daca M1 se opreste pentru w. m1. T1.

Rezulta deci ca pentru M2 se va utiliza un alfabet care contine perechi de simboli din alfabetul T1..... 3.{#})*. .. Vom nota cu T-1 o multime definita in modul urmator : T-1 = {aa E T1} In acest caz T2 = {$} U T1 U (T1 x T1) U (T1 x T-1) U (T-1 x T1). Banda de intrare pentru M2 se obtine prin indoirea benzii de intrare a masinii M1.Demonstratie. se imparte banda de intrare in doua piste si se copiaza sirul de intrare pe pista superioara. Adica.. Adica. M2 simuleaza M1 in modul urmator : 1.. b) va indica faptul ca a este continut de pista superioara iar b este continut de pista inferioara. respectiv functionarea masini M1 in partea stinga corespunde functionarii masini M2 pe pista inferioara a benzii sale de intrare. Pentru a realiza prima etapa trebuie sa se realizeze o prelucrare de siruri. daca consideram ca 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 +--------------------------In simulare se va considera deci ca functionarea masini M1 in partea dreapta a benzii de intrare corespunde functionarii masini M2 pe pista superioara a benzii sale de intrare.# # # . se simuleaza functionarea M1 pe banda obtinuta. an E (T1 . Etapa a doua poate sa fie realizata de catre o masina M1' . an # # ---------------------------------------^ trebuie sa se ajunga la un continut al benzii de forma : +-----------------------------------a1 a2 . dintr-o banda de intrare de forma : ---------------------------------------# a1 a2 .. # # +-----------------------------------^ unde a1. O astfel de pereche (a.. 2. Se observa ca prelucrarile necesare nu sint deosebit de dificile. an # $ ----+----+----+----+---. se reface forma initiala a benzii. cind si daca M1 se opreste.

2>. 2>.(a1.b) atunci / (<p. L) daca b = L m1'(<q.. 2>. 1>. 1>. 2>. R) daca b = L m1'(<q.. $) = (<q. (a-1. 1> si <q. 2>. R) m1'(<q. 2> care reprezinta oprirea in situatia in care M1' lucra pe pista superioara respectiv inferioara. a2) E T1 x T1 si m1(q. #)) e) daca a1. (a1. 2>. a2 E T1 atunci m1'(<h. Functia de tranzitie m' pentru M1' este definita in modul urmator : a) daca q E S1. Se observa ca in cazurile a si b este descrisa functionarea masinii M1 la dreapta si respectiv la stinga "mijlocului" ales.(a1. Cazul e trateaza intrarea in starea de oprire (h) a masini simulate M1..a2) = (<p. #) = (<q. (a1. Daca banda de intrare a masini M1 contine sirul w E (T1 {#})* si aceasta se opreste cu un continut de forma : ----------------------------------------------# b1 b2 . b) atunci / (<p. #) = (<q. 1>. 1>. indica modul in care se face extinderea celor doua piste la dreapta. 1> si <h. b)) daca b E T1 c) daca q E S1 U {h} atunci m1'(<q. (a1. De asemenea exista starile <h. Daca M1' este in starea <q. 1> inseamna ca M1' actioneaza asupra pistei superioare a benzii de intrare. Daca M1' este intr-o stare <q. a2)) = (h.care are in multimea sa de stari pentru fiecare q E S1 o pereche de stari notate <q. (a1. a2)) m1'(<h. 1>. a-2)) f) pentru situatiile care nu se incadreaza in nici unul dintre cazurile anterioare m1' se defineste arbitrar. a2) E T1 x T1 si m1(q.2>. 2>. 2> atunci inseamna ca M1' actioneaza asupra pistei inferioare.a2) = (<p. Cazul d. Se observa ca la intrarea in aceasta stare se va produce intrarea in starea h si a masinii M1' cu inregistrarea pistei pe care s-a facut oprirea masinii simulate. bi . trateaza comutarea intre piste care trebuie realizata atunci cind se ajunge la limita din stinga a benzii. 2>. 1>. a2) = (p. R) daca b = R \ (<p. (b.. R) d) daca q E S1 U {h} atunci m1'(<q. bn # # ----------------------------------------------^ atunci M1' se va opri cu un continut de forma : +------------------------------------- . 1>.1>. (a1. a2)) = (h. 2>. L) daca b = R \ (<p. 1>. a2)) daca b E T1 b) daca q E S1. (#. #)) m1'(<q. a1) = (p. Cazul c. (a1. $) = (<q. (#.

... Pentru etapa a treia se face translatarea simbolilor diferiti de # de pe pista inferioara pe pista superioara : +------------------------------------------b1 b2 . bi .. bn # . Orice functie care este calculata si orice limbaj care este acceptat sau decis de o masina Turing cu banda infinita la ambele capete este calculata respectiv acceptat sau decis de o masina Turing standard.. bi-1 b... In final se reface banda sub forma : +------------------------------------------# b1 b2 .. Si anume daca T1 si T2 sint doua multimi de tip alfabet care nu contin simbolul # atunci spunem ca functia f : T1* --> T2* este calculata de masina Turing. bn # +------------------------------------------^ Rolul alfabetului T1.. Extinderea masini Turing se poate face si prin renuntarea la caracterul determinist al acestora. # b1b2 . c2k ------+------+-----+----. Din acest motiv in tratarea pe care o vom realiza in continuare putem sa consideram pentru a simplifica demonstratiile in loc de masini Turing standard masini care au oricare dintre extensiile amintite sau chiar combinatii ale acestora. daca si numai daca pentru orice w E T1*. M care are banda de intrare infinita la ambele capete..u#).... # . daca f(w) = u atunci (q.. Similar definitiei din cazul masinilor Turing standard putem sa consideram si in acest caz definitia notiunii de calcul. De asemenea notiunile de acceptare respectiv de decidabilitate referitoare la limbaje pot sa fie definite pentru masinile Turing cu banda infinita la ambele capete intr-o maniera similara celei de la masina Turing standard.. Pentru o masina Turing nedeterminista functia m este definita in modul urmator : m : S x T --> P((S U {h}) x (T U {L. bn $ ----+----+-----+----+-----+---.. In cazul masinilor Turing nedeterministe deoarece pentru . # cu bi =/ #...ck+1 ck+2 . Cu alte cuvinte automatele push down nedeterministe sint "mai puternice" decit cele deterministe deoarece automatele push down nedeterministe accepta o clasa mai larga de limbaje..bi+1 ..# ck ck-1 . 1 <= i <= n. bi . In cazul automatelor push down aceasta echivalenta nu exista. # +------------------------------------------^ Din nou aceasta prelucrare este simpla..# # # .utilizat in construirea masinii M1' este de a permite identificarea pozitiei capului la oprirea masinii M1'. R})) Dupa cum s-a aratat pentru orice automat finit nedeterminist se poate construi un automat finit determinist echivalent.. c2k = # .. Constructii si rezultate similare pot fi realizate si pentru celelalte extensii considerate la inceputul acestui subcapitol... c1 +------------------------------------$ unde c1c2 .. w#) -* (h.

Fie . la intilnirea unui simbol b. Propozitie Pentru orice masina Turing. La un moment dat.# b. deoarece m(q.C'. Fie M1 = (S. Sa consideram o schita de demonstratie pentru propozitia anterioara.# a. In acest caz ceea ce conteaza este ca masina Turing se opreste in una din evolutiile sale posibile. Masina Turing porneste spre stinga.# # ---------->-------->-<--------<---------/ # \ Configuratia din care se pleaca este (q. Find vorba de o functionare nedeterminista tot ce conteaza este ca dintre toate solutiile posibile exista una pentru care masina se opreste. Se pune problema cum trebuie sa faca M2 cautarea intre aceste evolutii (in ce ordine ?). Rezultatul depus pe banda nu este in acest caz neaparat semnificativ. M1 poate avea insa un numar infinit de evolutii pornind din s si avind un sir w pe banda de intrare ( sa nu uitam ca daca sirul nu este acceptat de M1 aceasta nu se va opri). Daca starea curenta este q si simbolul curent la intrare este a. b -\/ b a a b a / _ >L ------> L ------> L ------> L ------> L ------> a R # \ # b. Vom restringe putin problema considerind numai notiunea de acceptare. s). Fie limbajul L = { w E { a. M2 trebuie sa incerce toate evolutiile posibile pentru M1 in cautarea unei evolutii pentru care M1 se opreste. ii) daca M1 nu se opreste pentru w atunci nici M2 nu se opreste pentru w. Se poate demonstra urmatoarea propozitie. atunci m(q. R})) este o multime finita. a) E P((S U {h}) x (T U {L. limbajul este de tip regulat si poate sa fie acceptat de un automat finit determinist. Daca ghicirea este corecta atunci masina se va opri. m. #w#). se pune problema cum se alege "calculul util" efectuat de masina Turing. Sa consideram mai intii un exemplu de masina Turing nedeterminista. O solutie de masina Turing nedeterminista care accepta acest limbaj este : a. masina Turing "ghiceste" ca a gasit sfirsitul subsirului cautat. altfel masina nu se opreste.a) <= ( S + 1) x ( T + 2).acelasi sir de intrare se pot obtine rezultate diferite. b}* w contine sirul abaab} Evident. Ideea este urmatoarea.# b. M1 nedeterminista exista o masina Turing M2 determinista (standard) astfel incit pentru orice sir w care nu contine simbolul # : i) daca M1 se opreste pentru w atunci si M2 se va opri pentru w. daca M1 este in configuratia C atunci exista mai multe configuratii C' astfel incit C . T1. Numarul configuratiilor C' este insa finit si depinde numai de definitia functiei m (nu de configuratia C).

uav) . Corespunzator M2 va descoperi aceasta oprire intr-un numar finit de pasi.(q'.. P. a). Fiecare simulare incepe cu o copiere a continutului primei benzi (partea utila) pe a doua banda. etc. Fiecare dintre aceste r configuratii diferite poate sa treaca la rindul ei in alte r configuratii diferite. S) astfel incit pentru orice pereche de configuratii (q. m. TM.. q E S.#w#) M1 poate sa treaca in maximum r configuratii urmatoare diferite. TG. Fie M = (Q. A treia banda pastreaza evidenta incercarilor facute. Daca in aceasta alegere nu exista o altenativa cu numarul celei indicate se abandoneaza calculul.. Pe baza propozitiei enuntate anterior rezulta ca orice limbaj acceptat de o masina Turing nedeterminista va fi acceptat si de o masina Turing determinista.3. Rezulta deci ca pentru o evolutie in k pasi se poate ajunge la un numar de maximum rk configuratii diferite pornind din configuratia initiala. Pe aceasta banda se vor genera siruri care codifica modul in care se aleg alternativele posibile in fiecare pas al simularii. Pentru fiecare multime m(q. dr}. Masina M2 poate sa fie construita avind trei piste. . Se observa ca toate prelucrarile descrise anterior sint prelucrari simple asupra unor siruri de simboli ce pot sa fie realizate de catre masini Turing standard. 1.5. u'a'v') ale masini Turing * (q. In primul pas se alege daca exista a treia alternativa din cele maximum r posibile. Astfel. Daca in aceasta cautare se trece printr-o configuratie pentru care M1 se opreste se va opri si M2. consideram cite o ordonare arbitrara a elementelor care o compun. apoi in doi pasi. pe ea se pastreaza sirul initial. Relatia intre masina Turing si gramatici Propozitie. Si anume pe aceasta banda se gaseste un sir dintr-un alfabet D = {d1. A doua pista este utilizata pentru a simula functionarea masini M1. M2 va analiza in mod sistematic intii toate configuratiile in care se poate ajunge intr-un pas. Dupa fiecare incercare care nu a dus la oprire se va sterge continutul celei de a doua benzi si se genereaza un nou sir pe a treia banda. Generarea sirurilor pe a treia banda se face in ordine lexicografica.a) ) q E S a E T Valoarea r rezulta din definitia functiei m si reprezinta numarul maxim de configuratii urmatoare posibile pentru o configuratie data. O pista este utilizata ca martor. un sir de forma d3 d5 d1 indica faptul ca se va incerca un calcul in trei pasi. Deci daca pornim din configuratia initiala C = (q. Daca M1 se opreste vreodata atunci ea se opreste intr-un numar finit de pasi. in al doilea pas se alege a cincea alternativa iar in al treilea pas se alege prima alternativa posibila. Daca incercarea duce la oprirea masini simulate se opreste si M2. q) o masina Turing. a E T. unde r este numarul maxim de configuratii urmatoare posibile pentru orice configuratie a masini M1. Exista o gramatica G = (N.r = max ( m(q. uav) si (q'. u'a'v') M daca si numai daca .

(h.q E Q. u. pentru o configuratie de forma (q.w) se obtine o forma propozitionala [uqaw].c E TM U {]} daca a = # atunci bq#] --> pb] E P. Mai departe rezultatul se extinde natural pentru inchiderile acestor relatii. V. V.a E TM daca m(q. (q1. Pozitia pe care o ocupa simbolul corespunzator starii indica de fapt pozitia capului de citire pe banda de intrare. q0) pentru care m este definita in modul urmator : m(q0. m.a) = (p. #}. m(q2. v') daca si numai daca [uqav] ==> [u'q'a'v'] Demonstratia se realizeaza considerind toate formele posibile de productii. b) b E T atunci qa --> pb E P ii) V. S}. Sa consideram de exemplu masina Turing M = ({q0. (q2. Multimea simbolilor neterminali N = Q U {h. a.a) = (p. Pozitia sa in cadrul fiecarui sir reprezinta de fapt pozitia capului de citire. In toate productile se observa ca apare cite un singur neterminal atit in partea dreapta cit si in partea stinga.a E TM daca m(q. R) atunci qab --> apb E P pentru V. Se poate demonstra utilizind aceasta constructie ca : (q. {a. Se observa ca formele propozitionale ce se obtin in gramatica G contin siruri care corespund configuratilor masini Turing.* [uqav] ==> [u'q'a'v'] G Demonstratie. v) . V.a) = (p. m(q1. Simbolul de start al gramaticii nu este utilizat. (q0. m(q0.a. Se observa ca in constructia anterioara simbolul de start al gramatici nu joaca nici un rol. (q2. m(q1.a E TM daca m(q. a'.q E Q.b E TM. L) atunci daca a =/ # sau c =/ ] atunci bqac --> pbac E P. R) a) R) a) #) R) sa consideram pentru aceasta masina evolutia pentru configuratia . q1. q2}. a) #) a) #) #) a) = = = = = = (q1.u.(q'. Multimea simbolilor terminali pentru G este TG = TM U {[. V. u'. Multimea productiilor se construieste in modul urmator : i) V. ]}. Acest neterminal corespunde unei stari. Astfel. V. m(q2.b E TM si qa] --> ap# E P iii) V. V.q E Q.b E TM.

S) astfel incit T1. P. P. q1. {q. . Sa consideram de exemplu T1 = {a. a) ) q1# --> q1 a ( corespunde m(q1. Gramatica este in acest caz utilizata ca mecanism de specificare a unor substitutii de siruri si nu ca generator de limabj. aa#). #a#) . R)) q0a# --> a q1 # q0a] --> a q1 #] q1aa --> a q2 a (corespunde m(q1. S) P va contine urmatoarele productii : i) in cazul in care se face scriere pe banda q0# --> q0 a ( corespunde m(q0.(q1.(q0. S}. In acest caz se spune ca G calculeaza functia f. a) = (q2. R)) q2a# --> a q2 # q2a] --> a q2 #] Un calcul realizat de M poate sa fie : (q0.(q0. h. #a#) (q0. R)) q1a# --> a q2 # q1a] --> a q2 # ] q2aa --> a q2 a (corespunde m(q2.v E T2* v = f(u) daca si numai daca xuy ==*> x'vy'. P. #) = (q0. x'. b} si f : T1* --> T1*.(q2. a) ) q2# --> h # ( corespunde m(q2. ]}.(h. a) = (q1. aa#) -+ (h.(q1. a#) . y' E (N U T)* care indeplinesc urmatoarea conditie pentru V. #) = (h. #. T. #) = (q1. #) ) ii) in cazul in care se fac deplasari dreapta q0aa --> a q1 a ( corespunde m(q0. y. De la siruri definitia se poate extinde la numere naturale intr-o maniera similara celei utilizate la masina Turing. [. aa#) . aa#) . aa# . a#) .(q1. aa#) O derivare in G care porneste din sirul [q0#] este : [q0#] ==> [q0a] ==> [aq1#] ==> [aq1a] ==> [aaq2#] ==> [aah#] Se observa ca in aceasta derivare simbolul de start al garamtici nu a intervenit. a) = (q2. q2. Functia f este calculabila de catre gramatica G = (N. Sa construim gramatica corespunzatoare : G = ({q0.(q0. Fie T1 si T2 doua multimi de tip alfabet care nu contin simbolul # si fie f : T1* --> T2* spunem ca f este calculabila gramatical daca si numai daca exista o gramatica G = (N. T2 C_ T si exista sirurile x. #) .u E T1* si V. Asa cum o masina Turing a fost tratata ca acceptor de limbaj o gramatica poate sa fie privita ca un dispozitiv capabil sa reprezinte (efectueze) calcule. f(w) = wR. T.

Propozitie Orice functie calculabila Turing este calculabila si gramatical. avind in vedere ca o gramatica poate sa fie interpretata si ca un dispozitiv capabil sa efectueze calcule. G transforma un sir de forma [w*] cu w E {a. automatele push down. T. mai ales pentru a oferi o caracterizare a posibilitatilor oferite de acestea.5. A* --> *a.4. Elemente de calculabilitate Discutia continuta in acest subcapitol depaseste cadrul limbajelor formale dar este importanta pentru a realiza legatura dintre modelele de calcul considerate si lumea reala a calculatoarelor. P. ]} iar P contine urmatoarele productii : 1. De exemplu pentru sirul abb se obtine : [abb*] ==> [Abb*] ==> [bAb*] ==> [BAb*] ==> [BbA*] ==> [Bb*a] ==> [bB*a] ==> [b*ba] ==> [B*ba] ==> [*bba] Se observa ca nu este semnificativa ordinea in care se aplica productiile. Bb --> bB 3. T = {a. O astfel de masina se poate obtine de exemplu utilizind cite o masina Turing pentru fiecare productie. Gramaticile. S). [* si respectiv ]. B* --> *b Sirurile x. Aa --> aA. Se transforma intii primul simbol (a sau b) cu care incepe sirul in A sau B utilizind una dintre productiile [a --> [A sau [b --> [B. In continuare neterminalul astfel obtinut migreaza spre limita din dreapta a sirului. S}. [a --> [A.[b --> [B 2. De asemenea. *. Avind in vedere modul in care se obtine un sir care face parte din L(G) se poate construi o masina Turing eventual nedeterminista care sa realizeze aceleasi operatii. x' si y' sint [. adica pornind de la o masina Turing se construieste o gramatica care realizeaza acelasi calcul.S} unde N = {A. se pune intrebarea daca nu exista mecanisme mai puternice de reprezentare decit gramaticile si masina Turing (avind in vedere . Din rezultatele prezentate putem trage concluzia echivalentei intre gramaticile de tip 0 (fara restrictii) si masinile Turing din punctul de vedere al limbajelor acceptate (generate) si al puterii de calcul. masina Turing sint astfel de reprezentari finite. *]. B. b. [. Demonstratia acestei propozitii este constructiva. 1. Ba --> aB. y. Ab --> bA. se poate construi o masina Turing care sa execute operatia de derivare. b}* in modul urmator. La intilnirea simbolului * se aplica una dintre productiile A* --> *a sau B* --> *b. Considerind echivalenta dintre gramatici si masinile Turing se pune intrebarea cum se poate construi o masina Turing care sa accepte limbajul generat de o gramatica G = (N. In momentul in care s-a dat definitia limbajelor s-a precizat faptul ca numai o anumita parte a acestora poate sa fie descrisa intr-o forma finita. Avind in vedere ca operatia de derivare presupune de fapt prelucrari simple de siruri de simboli. Se pune problema daca odata cu masina Turing s-a atins intr-adevar limita de reprezentare finita a limbajelor. automatele finite.

. Fiecare masina Turing este definita utilizind patru elemente MT = (S. acelasi lucru este valabil si pentru fiecare simbol din alfabetul de intrare. m. T. astfel incit pentru orice masina Turing. O asemenea reprezentare sub forma de sir. Si anume o masina Turing standard este dedicata rezolvarii unei anumite probleme (calculului unei anumite functii) in timp ce un calculator este un dispozitiv universal. paranteze.}. Ar apare aici o diferenta importanta intre o masina Turing si un calculator real. . capabil sa treaca la calculul unei noi functii prin schimbarea programului. a2...mai ales faptul ca un calculator real pare mult mai puternic decit o masina Turing). Fie .s). nu este recomandabila deoarece avem nevoie pentru masina pe care o construim de un alfabet finit pe care sa il utilizam in definitia acesteia. deci a ceva continut in memorie. sa primeasca la intrare atit sirul care se transforma cit si o descriere a transformarii.. alfabet care sa permita reprezentarea oricarui alfabet posibil pentru o masina Turing. modelul Von Neumann de calculator presupune notiunea de program memorat. Fie c un simbol c =/ I. virgule si alte semne de punctuatie. q2. fara a schimba insa modul de functionare a unitatii de control. Se pune intrebarea daca nu se poate construi o masina Turing care sa functioneze intr-o maniera similara adica. multimea starilor si respectiv alfabetul de intrare sint submultimi finite din Sinf si respectiv Tinf. . Vom considera ca exista multimile infinit numarabile : Sinf = {q1.} si Tinf = {a1. O astfel de masina Turing se numeste masina Turing universala. Deoarece S si T sint multimi finite descrierea unei masini Turing poate sa fie scrisa sub forma unui sir utilizind simboli din S. Pentru a construi o masina Turing universala este necesar sa obtinem intii un mod de descriere al unei masini Turing sub forma de sir astfel incit aceasta descriere sa poata sa fie utilizata ca intrare pentru o alta masina Turing . Pentru construirea sirului care descrie o masina Turing se utilizeaza numai simbolii c si I. Se considera urmatoarea codificare pentru elementele care apartin unei definitii de masina Turing utilizind un alfabet ce contine un singur simbol {I} : element cod(element) ---------+-------------i+1 qi I ---------+-------------h I ---------+-------------L I ---------+-------------R II ---------+-------------i+2 ai I -----------------------Se observa ca fiecare stare q E S U {h} are un cod unic. T. Masina Turing Universala Spre deosebire de o masina Turing standard.

j3 = 6... Construim kl siruri notate cu Spr. De asemenea pe baza unui astfel de sir se poate reconstrui descrierea "clasica" a masinii.R) cIIIcIIIIIcIIIcIIc -----+---------------------+----------------------S13 m(q2.. a6) = (q2. a3) = (q2..Mai mult pentru o astfel de oprire continutul benzii U reprezinta o codificare a raspunsului masini Turing. Deci S = {qi1. Utilizind notatiile anterioare. unde 1 <= p <= k si 1 <= r <= l. T. l = 3 si j1 = 1. {I.. Se observa ca sirul astfel obtinut reprezinta o codificare unica pentru o masina Turing. aj2. #codif(M) codif(w) #) -*U (h. k.. Fie de exemplu m(qip. M pentru w. i1 = 2. Daca w = b1 . a3. Se obtine : S11 m(q2. R) cIIIcIIIIIIIIcIIIcIIc Rezulta codif(M) = cI3c cI3cI3cIcI5c cI3cI5cI3cI2c cI3cI8cI3cI2c c O masina Turing universala U primeste pe banda de intrare un sir de tip codif(M) si un sir w pe care trebuie sa functioneze M. T = {a1.. Sirul w trebuie sa fie si el codificat utilizind alfabetul {c. v astfel incit (h. iar T = {aj1. #codif(uav)#) 2. < ik. Adica daca M se opreste pentru w atunci si U se opreste pentru un sir obtinut prin concatenarea sirurilor codif(M) si codif(w). . Fiecare sir Spr codifica valoarea functiei de tranzitie pentru o pereche (qip. rezulta k = 1. qi2.a3).. qik}. qu) trebuie sa satisfaca urmatoarele conditii pentru orice masina Turing . s) o masina Turing cu S C Sinf si T C Tinf... a6}. #codif(M)codif(w)#) -*U (h. a. De asemenea daca U se opreste pentru un sir care reprezinta codif(M)codif(w) atunci si M se va opri pentru w si rezultatul lasat de U reprezinta codificarea rezultatului lasat de M. Codificarea se face in modul urmator. i1 < i2 < .. uav). u' = #codif(uav) pentru u.. Notam cu codif(M) sirul cS0cS11S12 . S0 este codificarea starii initiale. T. uav) atunci. daca (h. mu. M = (S.. U = (Qu. T.MT = (S. bn. a3) = m(q2. Sk1 Sk2 . R) si m(q2. I}.. a1) = (h. #}. R} atunci Spr = cw1cw2cw3cw4c unde : w1 w2 w3 w4 = = = = cod(qip) cod(ajr) cod(q') cod(b). Se observa ca sirul obtinut codif(w) nu poate sa contina simboli #. S0 = cod(s).s) cu S = {q2}. Sa consideram de exemplu MT = (S. b). daca (qu. #w#) -*M (h. S2l .. uav) este o configuratie de oprire pentru M si (s. u'a'v') pentru U atunci a' = #. ajr) = (q'. a1) = (h. uaw) este o configuratie de oprire pentru M astfel incit (s. cu bi E Tinf atunci codif(w) = c cod(b1) c cod(b2) c . chiar daca w contine simboli #. Skl c. a3) cIIIcIIIcIcIIIIIc -----+---------------------+----------------------S12 m(q2. c. . ajr). c cod(bn) c. #w#) -*M (h. j2 = 3. S1lS21 . q' E S U {h} si b E T U {L. m. (qu.. v' = ?. m. s = q2 si m(q2. m. s) : 1.. a6) = (q2.u'a'v') pentru o configuratie de oprire (h.

pentru prima banda pe ultimul c care indica sfirsitul codului pentru simbolul curent parcurs de M. a doua banda contine in timpul simularii codif(M) iar a treia banda va contine codificarea starii curente a masini M care se simuleaza. Cu alte cuvinte putem sa dam o reprezentare finita pentru un astfel de limbaj ?. Functionarea incepe cu prima banda continind codif(M)codif(w).pentru a doua si a treia banda la marginea stinga a benzilor respective. La identificarea unui astfel de subsir U' se va misca corespunzator. varianta care utilizeaza trei benzi. Din codif(M) se identifica S0 (codul pentru starea initiala) si se copiaza pe cea de a treia banda. Se observa ca localizarea inceputului sirului codif(w) in sirul initial se face usor pentru ca aici exista trei simboli c consecutivi. In continuare U' incepe sa simuleze functionarea masini Turing M. rezulta deci ca ar exista o masina Turing care sa verifice daca sirul face parte din limbaj.Pentru a simplifica discutia vom considera o varianta U' a masini U. Intre pasii de simulare cele trei capete de citire / scriere utilizate (exista trei benzi de intrare) sint pozitionate in modul urmator : . iar Ij este sirul curent de pe prima banda. Acest rezultat care este acceptat. adica limbajul este Turing decidabil ceea ce contrazice ipoteza. Rezulta deci ca o masina Turing este suficient de puternica pentru a fi comparata cu un calculator real. Daca asa ceva este posibil inseamna ca putem sa construim un algoritm care sa decida daca un sir face parte din limbajul respectiv. ci indica numai faptul ca un anumit obiect matematic (masina Turing) este echivalent cu un concept informal. U' va cauta pe a doua banda un subsir de forma ccIicIjcIkcIlcc unde Ii este sirul continut in a treia banda. U' va incepe simularea deplasindu-si capul pe ultimul simbol c de pe banda. U' va copia sirul codif(M) pe a doua banda si va modifica continutul primei benzi la forma #c codif(#w#). in prezent constituie numai o ipoteza pentru ca nu constituie un rezultat matematic. celelalte benzi find goale. Conform ipotezei Church insa notiunea de algoritm si cel de masina Turing sint echivalente. . Revenind la problema reprezentari finite a limbajelor se pune problema cum arata limbajele care nu sint Turing decidabile. . Mai mult conform ipotezei Church (Church's Thesis) nici o procedura de calcul nu este un algoritm daca nu poate sa fie reprezentata de o masina Turing. Prima banda va contine initial codif(M)codif(w). Daca Il este codif(L) sau codif(R) atunci se realizeaza deplasarea pe prima banda de intrare in mod corespunzator. In cadrul aceleiasi miscari U' inlocuieste sirul inscris in a treia banda cu Ik. Daca Il este cod(a) pentru a E Tinf se observa ca inlocuirea simbolului curent poate sa presupuna deplasarea continutului primei benzi pentru ca spatiul ocupat de codul pentru a poate sa fie diferit de cel ocupat de simbolul inlocuit. Conform celor mentionate anterior pentru aceasta varianta se poate construi o masina Turing echivalenta cu o singura banda. Daca pe banda a treia nu se gaseste cod(h) atunci se continua simularea. De fapt o masina Turing este echivalenta cu notiunea intuitiva de algoritm. In acest mod cind M porneste sa trateze ultimul simbol # din sirul de intrare #w#. Daca acum continutul acestei benzi este cod(h) U' va deplasa capul de pe prima banda pe primul simbol # aflat la dreapta pozitiei curente dupa care se opreste.

Demonstratie. w este codif(M) pentru o masina Turing . w ? sint echivalente. Propozitie. daca aceasta se opreste sau nu pentru un sir. Sa presupunem acum ca orice limbaj acceptabil este decidabil. In mod corespunzator raspunsul la cele doua probleme enuntate anterior este : NU. Se pot demonstra urmatoarele rezultate. Se pune intrebarea care este raportul invers intre limbajele acceptabile si cele decidabile Turing. este un limbaj decidabil.este orice limbaj Turing acceptabil si Turing decidabil ? . M' va intra intr-un ciclu infinit. N / >ML -------> N \ Se observa ca M' simuleaza M dupa care studiaza raspunsul obtinut pe banda. Din definitia limbajului L0.Sa discutam putin si relatia dintre limbajele Turing acceptabile si limbajele Turing decidabile. Orice limbaj L Turing decidabil este si Turing acceptabil. Fie M+ masina Turing care decide acest limbaj. Daca raspunsul este N. In acest caz M+ poate sa prevada pentru orice masina Turing daca aceasta se opreste sau nu pentru orice sir w. Daca L0 este Turing decidabil atunci limbajul : L1 = { codif(M) M accepta codif(M) } este Turing decidabil. M2 va executa calculele necesare pentru o prevedea daca M1 se opreste pentru w. Corespunzator M2 se va opri cu un simbol D sau N pe banda dupa cum M1 accepta sau nu sirul w. Functionarea M1 consta din transformarea intrarii din #w# in #wcodif(w)# pe care va functiona apoi M0.se poate construi o masina Turing care sa prevada pentru orice masina Turing. Daca M0 decide L0 atunci se poate construi M1 care sa decida L1. In acest caz limbajul : L0 = { codif(M)codif(w) M accepta w} sa nu si si care este acceptat de masina Turing universala. Am aratat ca daca se poate construi o masina Turing care prevada pentru orice masina Turing daca aceasta se opreste sau pentru orice sir atunci orice limbaj acceptabil este decidabil. sa prevedem daca masina Turing se va opri pentru w. Fie M o masina Turing care decide L. deoarece daca M1 este masina Turing care accepta L putem sa construim M2 care decide L in modul urmator. De fapt cele doua probleme : . Deci M1 va calcula acelasi rezultat asupra sirului #w# ca si M0 asupra sirului #wcodif(w)#. M. Vom arata in continuare ca L0 nu este decidabil. atunci orice limbaj Turing acceptabil ar fi si Turing decidabil. Atunci se poate construi M' care sa accepte L. Daca ar fi posibil ca pentru orice masina Turing si orice sir de intrare w. M0 va scrie D pe banda daca si numai daca : a.

independent de context. O masina Turing care decide L-1 se obtine din masina Turing care decide L1 inversind la oprirea masini raspunsurile D si N. Se observa ca am gasit o problema pentru care nu avem o solutie sub forma de algoritm. M* a fost construita pentru a accepta L-1.dindu-se o masina Turing .dindu-se o masina Turing. accepta sirul w. care nu accepta sirul codif(M) } este decidabil. Dar asta este exact definitia limbajului L1.dindu-se doua masini Turing. M. L1 si deci L0 nu sint Turing decidabile.c}* w nu este codif(M) pentru nici o masina Turing sau w = codif(M) pentru o masina Turing.b. Alte probleme nedecidabile echivalente de fapt cu aceasta sint : . se opreste M pentru orice sir de intrare ? .M.dindu-se o gramatica G independenta de context este G ambigua ? . Limbajul L-1 nu este insa Turing acceptabil. Turing decidabil ? . se opreste M pentru sirul vid ? . M. De fapt L0 descrie cea mai cunoscuta problema nedecidabila si anume problema opriri masini Turing. Enuntul acestei probleme este : "sa se determine pentru o masina Turing. Rezulta ca este suficient sa aratam ca L1 nu este Turing decidabil. M1 si M2 se opresc ele pentru acelasi sir de intrare ? . exista un sir pentru care M se opreste ? . Din definitia limbajului L-1 rezulta ca : V. Deoarece L0 nu este Turing decidabil nu exista un algoritm care sa stabileasca daca o masina Turing oarecare se opreste pentru un sir oarecre. M este limbajul acceptat de M regulat. codif(M) E L-1 <==> M nu accepta codif(M) (1) dar. Sa presupunem ca L1 este Turing decidabil in acest caz si limbajul L-1 = { w E {I.dindu-se doua gramatici G1 si G2 arbitrare L(G1) = L(G2) ? . masina Turing M. adica L-1. M arbitrara daca se opreste pentru un sir dat ".dindu-se o masina Turing. Astfel de probleme se numesc nedecidabile (nerezolvabile). M. M. Sa presupunem ca exista o masina Turing M* care accepta L-1.dindu-se o masina Turing.dindu-se o gramatica G arbitrara este L(G) = O/ ? . adica sirul de intrare codif(M). adica : codif(M*) E L-1 => M* accepta codif(M*) (2) Din (1) si (2) rezulta M* nu accepta codif(M*) => M* accepta codif(M*) adica M* nu poate sa existe.

. inceput subsir -------------------------------buffer de intrare . O astfel de informatie este foarte utila pentru construirea mesajelor de eroare. constante. Sa consideram de exemplu sirurile de caractere 99....10. In primul caz este vorba de numarul 99 x 10 10 in al doilea caz de o expresie relationala. Astfel. Ceea ce trebuie sa se proiecteze pentru realizarea unui analizor lexical este deci specificarea unui astfel de automat..E10 . Daca analiza se opreste dupa identificarea punctului zecimal cu concluzia ca s-a identificat un numar real se observa ca in primul caz oprirea se face prea devreme iar in al doilea caz prea tirziu. deoarece se realizeaza o abstractizare a unei infinitati de siruri de intrare in atomi de tip .2.. In acest mod se obtine un "text" mai usor de prelucrat de catre celelalte componente ale compilatorului. analizorul lexical propriu zis constind dintr-un simulator care opereaza asupra acestei specificatii si a sirului de intrare..identificatori. De exemplu in cazul in care un limbaj utilizeaza numere complexe. iar actiune i este o procedura care se executa pentru fiecare subsir care corespunde modelului oferit de pi. se pune problema daca analizorul lexical va fi cel care va recunoaste o constanta de forma: (<real>. etc. Daca exista mai multe modele de aceasi lungime care sint satisfacute se va alege o conventie de alegere : de exemplu in ordinea p1. O solutie consta din identificarea acestor situatii realizindu-se asa numita cautare inainte. pentru cazul considerat dupa recunosterea sirului 99.. De asemenea prin eliminarea blancurilor si a altor separatori irelevanti (ca de exemplu comentarii).. Analiza lexicala Rolul analizei lexicale este de a traduce textul programului intr-o secventa de atomi lexicali. textul prelucrat se poate reduce drastic. pn {actiune n} unde pi este o expresie regulata.pn. care pot sa apara intr-un program FORTRAN.E se mai cerceteaza cel putin un caracter pentru a se hotari daca analiza trebuie sa se incheie la 99 sau trebuie sa continue pina la 99. Cind se proiecteaza un analizor lexical se pune in general problema care este nivelul de complexitate al atomilor lexicali considerati. Un analizor lexical functioneaza de fapt ca un automat finit. <real>) producind un atom lexical corespunzator sau recunoasterea unei astfel de constante ramine in sarcina nivelului analizei sintactice.E10 si 99.pn.EQ. O abordare mai buna consta din cautarea sistematica a celui mai lung subsir care satisface unul din modelele p1. De cele mai multe ori analiza lexicala realizeaza si alte activitati auxiliare ca de exemplu pastrarea evidentei numarului de linii citite.. In general un analizor lexical este specificat sub forma : p1 {actiune 1} p2 {actiune 2} .

In general automatul care rezulta este : ------------------------+---+ +-----+ ? N(p1) +---+ ----------> -.--> / +---+ / +---+ +-----+ +---+ / / ------------------------\ -------------------------> s0 \ \ \ +---+ +-----+ \ \ ? N(p2) +---+ +---+ \ ----------> -.. Se observa ca trebuie sa se construiasca un AFN care sa recunoasca o expresie regulata de forma p1 p2 . In acest scop se realizeaza simularea continua pina cind se obtine o multime de stari pentru care nu mai exista nici o tranzitie posibila pentru simbolul curent.--> +---+ +---+ +-----+ ------------------------Pentru a simula acest automat se utilizeaza o modificare a algoritmului de simulare a AFN pentru a asigura recunoasterea celui mai lung prefix care se potriveste unui model. Ori de cite ori intr-o multime de stari se adauga o stare .-------------------------------\ cap de citire \ +-----------+ simulator --------------+ automat +-----------+ +-----------+ tabela de tranzitii +-----------+ +-----------+ tabela proceduri tratare actiuni +-----------+ Sa vedem intii cum se construieste un automat finit nedeterminist pornind de la specificatiile analizorului lexical. ------------------------+---+ +-----+ ? N(pn) +---+ +---------> -.--> \ +---+ +---+ +-----+ ------------------------.... pn. De exemplu orice compilator are o limita (eventual foarte mare) pentru numarul de caractere dintr-un identificator. Se presupune ca limbajul este astfel incit bufferul de intrare nu poate fi mai scurt decit o lexema (sirul de caractere corespunzator unui atom lexical recunoscut).

Pentru exemplul anterior se obtine automatul determinist echivalent descris de urmatoarea tabela de tranzitii: intrare model recunoscut a b ---------------+----------------+--------------------{0. Sa consideram si varianta care utilizeaza un automat determinist.7} {2.4. Cind se ajunge in situatia de terminare se revine la ultima pozitie in sirul de intrare la care s-a facut o recunoastere a unui model.8} a (pentru 2) ---------------+----------------+--------------------{8} {8} a*b+ ---------------+----------------+--------------------{7} {7} {8} ---------------+----------------+--------------------stare .7} {7} {5.1.1. apoi va fi gasita starea 8 la care se revine dupa ce se ajunge la terminare dupa simbolul a de la sfirsitul sirului.4.finala se va memora atit pozitia in sirul de intrare cit si modelul pi corespunzator. Automatul finit nedeterminist corespunzator este: +---+ +-----+ ? a +---+ ----------> 1 ------> 2 / +---+ / +---+ +-----+ +---+ / +---+ +---+ +---+ +-----+ / ? a b b +---+ 0 --------------> 3 ------> 4 ------> 5 ------> 6 \ +---+ +---+ \ +---+ +---+ +---+ +-----+ \ +---+ +-----+ \ ? b +---+ ----------> 7 ------> 8 +---+ +---+ +-----+ / \ / \ -----a b Sa consideram comportarea acestui automat pentru sirul de intrare aaba : a a b a {0.7} {8} ---------------+----------------+--------------------{2. Sa consideram de exemplu un analizor lexical specificat in modul urmator : a abb a*b+ Pentru acest analizor nu s-au specificat actiunile corespunzatoare unitatilor lexicale. Daca in multimea respectiva exista deja o stare finala atunci se va memora numai unul dintre modele (conform conventiei stabilite).3.3.7} ---> {2.7} ---> {7} ---> {8} ---> O Se observa ca prima stare de acceptare este 2 in care se ajunge dupa primul simbol a.4.

Informatiile referitoare la acesti simboli sint utilizate atit in cadrul analizei sintactice cit si in faza de generare de cod.1.8} ---> o Se observa ca sirul recunoscut este abb.8} {8} abb -----------------------------------------------------Se observa ca starea {6.{5. Tabela de simboli este o structura de date al carui rol este de a memora informatii referitoare la atomii lexicali de tip identificator recunoscuti de catre analizorul lexical.8} contine doua stari finale deci recunoaste atit modelul a*b+ cit si abb.7} ---> {2.1.7} ---> {5. De exemplu pentru sirul abba evolutia va fi : a b b a {0. Interfata analizorului lexical Dupa cum se stie analizorul lexical functioneaza ca un modul in cadrul unui compilator sau a oricarui program care realizeaza prelucrari ce necesita identificarea unor siruri ce pot fi descrise de o gramatica regulata. Introducerea simbolilor in tabela de simboli se face de catre .8} a*b+ ---------------+----------------+--------------------{6. Consideram prin conventie ca model recunoscut abb.8} ---> {6.3. In functionarea sa analizorul lexical interactioneaza cu celelalte componente ale compilatorului prin intermediul unei interfete 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 +---------------+ Interactiunea cu fisierul sursa se face prin intermediul a doua subprograme : avans_intrare (care preia caracterul urmator din programul sursa) si revenire (care realizeza revenirea inapoi in textul sursa. 2. daca intodeauna revenirea se face cu un singur caracter se poate utiliza o functie de tip ungetc).8} {6.4.

In general este bine ca interfata cu sistemul de operare sa . etc.analizorul lexical. Procedura insert_s are ca argumente un sir de caractere si codul atomului lexical reprezentat de sir. cod_else). analizorul sintactic va putea sa completeze apoi intrarea in tabela de simboli cu informatiile corespunzatoare numelui unui tip. In cazul constantelor analizorul lexical realizeaza recunoasterea acestora si memoreaza valorile corespunzatoare in tabela de constante pentru a permite utilizarea ulterioara in cadrul generarii de cod. Daca se intilneste o eroare. variabila. Pentru cuvintele cheie de obicei se face o tratare speciala. Se observa deci de ce in majoritatea limbajelor de programare cuvintele cheie nu pot sa fie utilizate ca nume cu alta semnificatie in programe. In general intre analizorul lexical si analizorul sintactic trebuie sa se mai transfere si alte informatii ca de exemplu adresa in tabela de simboli sau in tabela de constante a unui identificator. insert_s("else". completarea informatiilor realizindu-se de catre analizorul sintactic care va sa adauga informatii ca de exemplu tipul simbolului (procedura. de exemplu se poate initializeaza tabela de simboli cu intrari corespunzatoare tuturor cuvintelor cheie din limbajul respectiv executind apeluri de forma : insert_s("if". 2. Rezultatul procedurii este adresa in tabela de simboli la care s-a facut memorarea simbolului. dupa introducerea in tabela de simboli a cuvintului intreg de catre analizorul lexical.2. eticheta. se pune problema localizarii sale cit mai precise si apoi a modului in care se continua analiza astfel incit in continuare sa se semnaleze cit mai putine erori care decurg din aceasta. Daca in tabela nu exista sirul cautat rezultatul este 0. Aspecte privind implementarea unui analizor lexical Un aspect important al interfetei analizorului lexical o constituie interfata cu sistemul de operare corespunzatoare citirii textului programului sursa. etc) si modul de utilizare. In acest mod in urmatoarele intilniri ale acestui cuvint analizorul lexical va putea sa transmita ca iesire atomul lexical corespunzator unui nume de tip. Procedura lookup_s are ca argument un sir iar ca rezultat adresa in tabela de simboli la care se gaseste simbolul reprezentat de sirul respectiv. sintactica si in generarea de cod. cod_if). cuvintul cheie respectiv constanta identificata de catre analizorul lexical. Un compilator recunoaste erori in toate fazele sale : analiza lexicala. Recunoasterea cuvintelor cheie va putea sa fie facuta apoi intr-un mod similar cu a oricarui alt identificator. Legatura cu tabela de simboli se face prin intermediul a doua proceduri : insert_s si lookup_s. Analizorul sintactic apeleaza de obicei analizorul lexical ca pe o functie care are ca valoare codul atomului lexical recunoscut de catre analizorul lexical. O astfel de tratare are avantajul ca in cazul in care se face o declaratie de tip de forma: typedef int intreg.

sa consideram de exemplu doua instructiuni: DO 5 I = 2. realizind un numar minim de copieri pentru caracterele parcurse. .7 si DO 5 I = 2 In FORTRAN blancurile se ignora. In limbajul PL/1 nu exista cuvinte rezervate (desi exista cuvinte cheie). .sa fie accesibil atit atomul lexical curent cit si cel anterior. xx si y daca in sirul de intrare se intilneste sirul xxy trebuie sa se mai citeasca inca un caracter pentru a se putea stabili daca este vorba de atomul lexical xxyy sau de atomii lexicali xx si y. Sa consideram citeva exemple clasice. Din acest motiv este posibila o instructiune care arata in modul urmator: if then then then = else. din acest buffer in bufferul prevazut in program. Rezulta ca un analizor lexical pentru un astfel de limbaj trebuie sa fie capabil sa revina pe sirul de intrare respectiv sa priveasca inainte in sirul de intrare. .functiile trebuie sa fie cit mai rapide.existenta unui mecanism care sa permita examinarea unor caractere in avans si revenirea pe sirul de intrare.fie cit mai bine separata de restul compilatorului pentru a se obtine un cod portabil prin pastrarea aspectelor dependente de masina in cadrul functiilor care formeaza aceasta interfata. Pentru a obtine o utilizare eficienta a operatiilor legate de accesul la disc este necesar ca dimensiunea bufferului sa fie . Corespunzator cuvintul cheie DO va putea sa fie recunoscut in prima instructiune numai pe baza recunoasterii caracterului ".". Pentru fiecare cuvint cheie analizorul lexical trebuie sa furnizeze cite un cod de atom lexical diferit in timp ce pentru orice identificator trebuie sa furnizeze acelasi cod de atom lexical. else else = then. In mod standard obtinerea unui caracter in executia unui program presupune copierea acestuia in mai multe etape . Un alt exemplu "clasic" este din limbajul FORTRAN. La rindul sau partea cea mai consumatoare de timp este de obicei partea legata de operatiile de citire. Din timpul consumat de catre procesul de compilare o parte foarte importanta se consuma in cadrul analizei lexicale. Analizorul lexical trebuie sa poata face deosebirea dintre cuvintele cheie si identificatori. de unde apoi se face copierea in bufferul care memoreaza caracterul curent.de pe disc in bufferul sistemului de operare. Chiar si in cazul unui analizor lexical foarte simplu care ar trebui sa recunoasca sirurile : xxyy.sa admita atomi lexicali suficient de lungi. Analizorul lexical poate face diferenta dintre cuvintul cheie else si identificatorul else pe baza de exemplu prezentei sau absentei caracterului "=" dupa numele respectiv. Se observa ca in acest caz utilizarea unei proceduri de tip ungetc() nu este suficienta. In general o colectie de functii care asigura citirea textului sursa pentru analizorul lexical trebuie sa satisfaca urmatoarele conditii: .

Analizorul lexical a mai parcurs citeva caractere si indicatorul curent este pozitionat pe caracterul urmator. atom lex ////// anterior curent ////// +-----------------------------------------------------------+ Amem Smem Amem reprezinta inceputul atomului lexical anterior. Corespunzator indicatorul curent nu trebuie sa depaseasca indicatorul pericol. Citirea textului de pe disc se face in unitati care sint multipli ai acestei constante. MAXLOOK reprezinta numarul maxim de caractere pe care analizorul le mai cerceteaza in dreapta atomului lexical curent. pentru sistemul de operare MS-DOS utilizarea unui buffer mai mic decit 512 octeti nu are nici o justificare (o operatie de citire va citi cel putin un sector de pe disc). MAXLEX reprezinta lungimea maxima a unui atom lexical. Emem indica sfirsitul atomului lexical curent. sfirsit_buf Start_buf pericol END Amem Smem Emem curent . Pointerul pericol indica momentul in care indicatorul curent a ajuns prea aproape fata de sfirsitul bufferului.adaptata modului de alocare a spatiului pe disc. Dupa ce analizorul lexical a preluat citiva atomi lexicali structura bufferului devine: Start_buf sfirsit_buf END Emem curent pericol / / / +-----------------------------------------------------------+ atom lex. Pointerul curent reprezinta pozitia caracterului util curent. In acest caz se face o deplasare la stinga a continutului bufferului si o reumplere a acestuia. Start_buf si END reprezinta inceputul si sfirsitul fizic al bufferului. De preferat este ca bufferul sa fie un multiplu al unitatii de alocare a spatiului pe disc. Situatia prezentata in desen este momentul initial. Smem indica inceputul atomului lexical curent. Daca analizorul lexical stabileste ca atomul lexical curent este mai mai lung va muta indicatorii in mod corespunzator. Sfirsit_buf reprezinta sfirsitul logic al bufferului. Datorita cercetarii pe care analizorul lexical trebuie sa o faca la dreapta atomului lexical curent tot timpul dupa indicatorul Emem trebuie sa mai existe MAXLOOK caractere. Astfel. Pentru satisfacerea criterilor impuse o solutie posibila este reprezentata de urmatoarea structura de buffer: Start_buf sfirsit_buf END curent pericol / +-----------------------------------------------------------+ ////// ////// +-----------------------------------------------------------+ <----> MAXLOOK <---------------------------------------------------------> lungime_buffer > n x MAXLEX + MAXLOOK unde lungime_buffer este dimensiunea bufferului.

/ +-----------------------------------------------------------+ atom lex atom lex ////// anterior curent ////// +-----------------------------------------------------------+ <------------> n * MAXLEX Procedura de intrare va completa bufferul prin citire de pe disc a unui multiplu de MAXLEX caractere. eof actiune calcul valoare introduce in tabela de simboli In afara de recunoasterea acestor atomi analizorul lexical realizeaza si o eliminare a blancurilor si a unor caractere speciale de tip '\n' sau '\t'. Tabela de simboli trebuie sa memoreze pentru fiecare .termen termen termen --> termen * factor termen / factor termen div factor termen mod factor factor factor --> (expresie) identificator numar identificator --> litera rest_id rest_id --> litera rest_id cifra rest_id ? numar --> cifra numar cifra litera --> A B . Un exemplu elementar de analizor lexical Sa consideram analizorul lexical corespunzator unui translator pentru limbajul descris de urmatoarea gramatica : S lista expresie --> lista eof --> expresie. Dupa aceasta citire se actualizeaza in mod corespunzator variabilele sfirsit_buf si pericol. 2. lista ? --> expresie + termen expresie ...3. Avind in vedere tipul atomilor lexicali ce trebuie recunoscuti nu este necesara utilizarea unei interfete sofisticate cu sistemul de operare. z cifra --> 0 1 2 3 4 5 6 7 8 9 Se observa ca nivelul analizei lexicale printr-o transformare corespunzatoare presupune recunoasterea urmatorilor atomi lexicali : atom lexical numar identificator div mod ( ) * / + .

In tabela.)/A1. Variabila tokenval primeste o valoare care depinde de tipul atomului lexical recunoscut. codul asociat (prin intermediul caruia va fi tratat de catre analizorul lexical) si eventual alte atribute semnificative pe care le poate adauga analiza sintactica./A1 +---+ -----------------------------------> EOF/A6 -----------------------------------> +---+ +-------+ +-----+ In graf au fost evidentiate caracterele si actiunile corespunzatoare acestora.\t /A7 cifra.fiecare intrare este asociata unui simbol.(/A1.//A1. Valoarea intoarsa de functia anlex() este codul atomului lexical recunoscut. -litera / A3 \/ -+-------+ \/ +-----+ litera / A2 +---+ =/ litera / A4 +---+ -------------> 1 ----------------> +---+ =/ cifra +---+ cifra / A3 +-----+ -\/ +-----+ cifra / A2 +---+ # cifra / A5 +---+ 0 -------------> 2 ----------------> +---+ +---+ +-----+ +-----+ */A1. si contine adresa in vectorul care memoreza sirurile si codul asociat simbolului respectiv. Interfata cu analizorul sintactic se realizeaza prin intermediul rezultatului apelului analizorului lexical (valoarea functiei anlex()) si prin variabila tokenval. Deoarece lungimea sirurilor care formeaza identificatorii poate sa fie foarte diferita pentru a se asigura o buna utilizare a memoriei se va utiliza o tabela de simboli formata dintr-un vector in care se inregistreaza sirurile corespunzatoare cuvintelor cheie si identificatorilor recunoscuti in textul sursa si o tabela cu doua sau mai multe colane. 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 sa fie decris de urmatorul graf : blanc.-/A1.sirul de caractere respectiv.. Astfel pentru un numar aceasta variabila va contine valoarea numarului iar pentru un identificator adresa in tabela de simboli (la care a fost .\n.+/A1.identificator (cuvint cheie) .

introduce un simbol nou la sfirsitul tabelei de simboli. Fiecare identificator este asamblat intr-un buffer auxiliar buffer_intrare. DIV(257).atom_lexical. insert(s. return NUMAR. tokenval = atoi(buffer_intrare). return GATA. caracter = getchar(). Rezultatul intors de aceasta procedura este adresa relativa in tabela de simboli. In legatura cu tabela de simboli programul contine trei proceduri : init() realizeaza introducerea in tabela de simboli a cuvintelor cheie lookup(s) .cauta in tabela de simboli sirul de caractere transmis ca argument. IDENTIFICATOR). else if (caracter == '\n') lineno++. p = lookup(buffer_intrare).introdus sau regasit identificatorul respectiv). A2 : b = 0 . Actiunile ce trebuie sa fie executate in legatura cu executia analizorului lexical sint urmatoarele : A1 : tokenval = NIMIC. MOD(258). Pentru ceilalti atomi lexicali codul corespunde codului ASCII al caracterului ce reprezinta atomul lexical respectiv. A7 : if (caracter == ' ' caracter == '\t') . return caracter. if (p == 0) p = insert(buffer_intrare. eventual se va introduce simbolul respectiv in tabela de simboli. stdin).t) . stdin). Al doilea argument de apel este codul atomului lexical reprezentat de sirul respectiv. return tabela_simboli [p]. A5 : buffer_intrare[b] = EOS. A3 : buffer_intrare[b++] = caracter. A4 : buffer_intrare[b] = EOS. if (b >= BSIZE) eroare("sir prea lung"). tokenval = p. GATA(260). IDENTIFICATOR(259). if (caracter != EOF) ungetc(caracter. In momentul in care se incheie construirea unui identificator (se identifica sfirsitul sirului) se poate face cautarea acestuia in tabela de simboli. if (caracter != EOF) ungetc(caracter. . A6 : tokenval = NIMIC. Atomii lexicali care presupun asignarea unor coduri distincte sint : NUMAR(256).

buffer_intrare[BSIZE]. "mod". b. /* ultimul caracter citit */ /* cod atom lexical */ /* numar linie cod */ . }. /* prototipuri functii */ static static static static static static int int void void void int lookup(char s[]).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]. 0 }. /* sir de nume identificatori */ struct intrare { char *lexptr. MOD. static struct intrare cuvinte_cheie[] = { "div". lineno = 1.int tok).h" "stdio. caracter. DIV. a3(void). int atom_lexical. init(void). static struct intrare tabela_simboli [MAXSIM]. p. tokenval = NIMIC. insert(char s[].h" "string. int int int int char int ultimul_caracter = -1. #include #include #include #include "stdlib. lexan(void). ultima_intrare = 0.h" "ctype. eroare (char *m). 0.Corespunzator va rezulta urmatorul program care citeste si afiseaza codurile atomilor lexicali intilniti.

lexptr = &sir_simboli[ultimul_caracter + 1].lexptr./* cauta in tabela de simboli */ static int lookup(char s[]) { int p. return ultima_intrare. int tok) { int len. for (p = ultima_intrare.lexptr. m). } /* tratarea erorilor */ static void eroare (char *m) { printf("line %d: %s\n". p--) if (strcmp(tabela_simboli[p]. for (p = cuvinte_cheie. } /* analizorul lexical */ static void a3() . p > 0. p -> atom_lexical. tabela_simboli[++ultima_intrare]. if (ultimul_caracter + len + 1 >= MAXSIR) eroare("s-a depasit dimensiunea tabelei de simboli"). ultimul_caracter = ultimul_caracter+len +1. tabela_simboli[ultima_intrare]. } /* initializarea tabelei de simboli */ static void init() { struct intrare *p. p->atom_lexical). strcpy(tabela_simboli[ultima_intrare]. } /* introducere in tabela de simboli */ static int insert(char s[]. return 0. len = strlen(s). lineno. exit(1).s). s) == 0) return p.atom_lexical = tok.p++) insert(p->lexptr. if (ultima_intrare + 1 >= MAXSIM) eroare("s-a depasit dimensiunea tabelei de simboli").

} static int lexan() { while(1) { caracter = getchar(). while (isalnum(caracter)) /* litera sau cifra */ /* A3 */ a3(). } else if (caracter == EOF) { /* A6 */ tokenval = NIMIC. } } } . IDENTIFICATOR). tokenval = atoi(buffer_intrare). /* eliminare blancuri si tab-uri */ else if (caracter == '\n') lineno++. return GATA. /* A7 */ if (caracter == ' ' caracter == '\t') . if (b >= BSIZE) eroare("sir prea lung"). stdin).{ buffer_intrare[b++] = caracter. } else if (isalpha(caracter)) /* caracter este litera */ { /* A2 */ b = 0. if (caracter != EOF) ungetc(caracter. if (p == 0) p = insert(buffer_intrare. if (caracter != EOF) ungetc(caracter.atom_lexical. while (isdigit(caracter)) /* A3 */ a3(). stdin). /* A4 */ buffer_intrare[b] = EOS. tokenval = p. return tabela_simboli [p]. else if (isdigit(caracter)) /* caracter este cifra */ { /* A2 */ b = 0. /* A5 */ buffer_intrare[b] = EOS. caracter = getchar(). return NUMAR. } else { /* A1 */ tokenval = NIMIC. return caracter. p = lookup(buffer_intrare).

Considerind gramatica expresiilor aritmetice : (1) (2) (3) (4) (5) (6) E E T T F F --> --> --> --> --> --> E + T T T * F F (E) a si sirul de intrare a * (a + a) sa construim o derivare stinga : 2 3 4 6 E ==> T ==> T * F ==> F * F ==> a 2 a * (E + T) ==> a * (T + T) 4 a * (a + T) ==> a * (a + F) 5 * F ==> a * (E) 4 ==> a * (F + T) 6 ==> a * (a + a) 1 ==> 6 ==> Lista productiilor aplicate este 23465124646.void main() { int simbol_curent. init(). E 4 T * (E + T) ==> 2 ==> T * (T + a) 4 ==> F * (a + a) 4 ==> 6 ==> . simbol_curent = lexan(). Faza de analiza sintactica nu construieste de obicei chiar o structura de date cu organizare de arbore ci o structura din care se poate deduce (reconstrui acesta).simbol_curent). while (simbol_curent != GATA) { printf(" %d\n". Pentru derivarea dreapta se obtine: 2 3 5 1 E ==> T ==> T * F ==> T * (E) ==> 6 T * (E + F) ==> T * (E + a) 6 T * (F + a) ==> T * (a + a) a * (a + a) In acest caz lista productiilor care trebuie sa fie aplicate pentru sintetizarea neterminalului de start al gramaticii este 64642641532. } } 3. simbol_curent = lexan(). Ambele liste de productii descriu acelasi arbore de derivare. De exemplu o lista cu numerele productiilor aplicate in derivarea respectiva contine toate informatiile din care se poate construi arborele de derivare. Analiza sintactica Rolul fazei de analiza sintactica este de a construi arborii de derivare corespunzatori sirurilor care fac parte din limbajul respectiv verificind buna structurare a acestora. Termenul utilizat in literatura de specialitate pentru aceasta actiune este "parsing".

Z. a E T*. (q. 4)} m(q. B E Z*.(q. t).a. ?. t E X*. X. In general pentru o gramatica independenta de context se poate construi un automat de tip push down care sa produca pentru un sir de intrare dat lista de productii care duce la acceptarea sirului respectiv.+.. E + T. iar functia m este definita ca m : S x (T U {?}) x Z --> P(S x Z* x X*). y E X*} Similar definitiilor referitoare la automatele push down exista notiunile de translatare prin stiva goala si translator push down extins. 1). z0. y) q E F. {1. Un astfel de translator se construieste adaugind o iesire unui automat push down. a. iar pentru derivarea drapta parcurgerea arborelui SDR. Deci definitia este: PDT = (S.2 T / \ 3 T * F 4 / \ 5 F ( E ) 6 / \ 1 a E + T 2 4 T F 4 6 F a 6 a Se observa ca pentru derivarea stinga este vorba de o parcurgere RSD.{E. y) q E F. E.{a.*. y) (q0. z0. 2)} m(q.(q.6)} . z0. (q. Pentru o gramatica independenta de context putem sa construim un translator push down care produce lista productiiilor corespunzatoare derivarilor stinga si dreapta. w. F. ?. Sa consideram din nou gramatica expresilor aritmetice.(. B. La fiecare miscare a automatului push down. a. a. translatorul va emite un sir finit de simboli. F) unde X este un alfabet finit de iesire.+. q. ?) -*. O/) cu m(q. Evident dindu-se o parcurgere si productiile gramaticii se poate reconstrui arborele de derivare. F.)}. B E Z*. 6}.?.. Rezulta translatorul care produce lista productiilor corespunzatoare derivarilor stinga : ({q}. . (q. T * F. T. m. q E S.*. ?) -*. E) = {(q. B. T) = {(q. 3). a E T*.)}. (E). Se spune ca automatul realizeaza traducerea sirului a E T* in sirul y E X* daca este indeplinita conditia : (q0. ?. In acest caz o configuratie a automatului are patru componente : (q. T.. w E Z* In general traducerile realizate de catre translator sint : { (a. 2.(. q0.a.?. T. F) = {(q. m. In acest scop se defineste notiunea de translator push down. unde t reprezinta sirul de simboli generat pina la momentul curent de catre automat. 5).

(q.m(q.(q. (q. * (a + a). $E. 6464264153) ?. $T. (q. ?. Exista gramatici pentru care aceasta conditie nu poate sa fie indeplinita. 23465124646) In cazul derivarii dreapta se obtine translatorul push down: ({q}. x) = {(q. m. {a.2. ?. $. ?) . (q.a.*.(q. ?. (a + a).?. . 64642) ). 64) (a + a). O/) cu m(q.(. (q.(q. $T * (E + a. 64642641532) ?. 646) + a). T. 2346) . m(q. T. ?) * (a + a). a * (a + a). a * (a + a). ?) (q. (q. (E). F * F. ?. 64642) a). m(q. $T * (E + F. 64642) ). * (a + a). $T * (E). 64642641532) Se observa ca cele doua translatoare construite sint nedeterministe. $T * (F. (q. $T * (E. {(q. q. (a + a).F. $T *. 6464264) ). $T * (E +. Se pune problema daca intodeauna un astfel de translator poate sa fie simulat determinist deoarece ceea ce ne intereseaza este sa obtinem analizoare sintactice respectiv compilatoare cit mai eficiente si cu o comportare determinista. m(q. 64) + a). F..(q. (q. F. $.$}. (q. a * (a + a).T. x. ?. 2) .6}. $T * (T. 6464) + a). {(q. (q.+. 64) + a). ?. 2346) . (q. a * (a + a).(.. ?. {(q. pentru o gramatica recursiva stinga nu se poate construi un translator care sa produca sirul productiilor dintr-o derivare stinga si sa poata sa fie simulat determinist. E. 23465) -+ (q. $T * (. (q. 234) .. F. {(q. (q. a * F. $T * (a. E. {(q.+. $F. ?)} x E T De exemplu pentru sirul a * (a + a) se obtine evolutia : (q. {(q. ?. x. (q. (q.*.. (q.). T.(q. m(q. ?. 646426) ). m(q. {(q. x. m(q. $T * (E. * F. {E. $T * F. $a. 64642641) ?. {1. m(q. E. E + T) T) T * F) F) (E)) a) ?) $E)} = = = = = = = = {(q. a * (a + a). $T.(q. (q.(q. $T * (E + T. ?. 23) . De exemplu. 6) * (a + a). 64) a + a). 2346) . ?. T * F. 64642641) ?.)}. (q. a * (a + a). 1)} 2)} 3)} 4)} 5)} 6)} ?)} ?)} x E T Pentru acelasi sir se obtine secventa de miscari: (q. 646426415) ?.

de la stinga (Left) la dreapta. In acest caz se avanseaza cu o pozitie pe sirul de intrare si in arborele de derivare.1. 3. A--> ab a si sirul de intrare cad. Se poate arata ca daca o gramatica este LL(k) ea este si LR(k) dar exista gramatici LR(k) care nu sint LL(k).down Analiza sintactica top-down poate sa fie interpretata ca operatia de construire a arborilor de derivare pornind de la radacina si adaugind subarbori de derivare intr-o ordine prestabilita. In acest moment frunza curenta din arborele de derivare este etichetata cu A si se aplica una din productiile corespunzatoare acestui neterminal : S / \ / \ c A d . Cu alte cuvinte gramaticile LL(k) sint un subset al gramaticilor LR(k). Construirea arborelui de derivare pentru acest sir porneste de la simbolul de start al gramaticii S si cu pointerul pe sirul de intrare pozitionat pe caracterul c. bottom up) exista cite o clasa de gramatici pentru care se poate construi un translator determinist daca translatorul are acces la urmatorii k simboli de pe sirul de intrare. In denumire prima litera (L) reprezinta tipul de parcurgere al sirului . Gramatica nu este nici LR(k) si nici LL(k) deoarece nu se stie daca primul a dintr-un sir din L(G) este generat utilizind productiile 1 si 5 sau 2 si 6. Analiza sintactica top . Se observa ca de fapt problema este ca nu se stie cite caractere trebuie sa fie cercetate in avans pentru a lua o decizie corecta. Sa consideram de exemplu gramatica S --> cAd. Aceasta informatie este aflata abia cind se ajunge la sfirsitul sirului si se citeste ultimul simbol. Sa consideram de exemplu urmatoarea gramatica : (1) (2) (3) (4) (5) (6) S S A A B C --> --> --> --> --> --> BAb CAc BA a a a Se observa ca L(G) = aa+b + aa+c. Cele doua clase se numesc LL(k) respectiv LR(k). Miscarile translatorului se fac tinind seama de starea curenta (starea unitatii de control si continut stiva) si de urmatorii k simboli de pe sirul de intrare.Pentru fiecare tip de analizor sintactic(top down. Pentru S se utilizeaza productia S --> cAd si se obtine arborele de derivare : S / \ / \ c A d In acest moment se observa ca frunza cea mai din stinga corespunde cu primul caracter din sirul de intrare. A doua litera (L sau R) specifica tipul derivarii stinga (Left) sau dreapta (Right).

O diagrama de tranzitie este un graf care prezinta productiile corespunzatoare unui neterminal. se creaza doua stari: initiala si finala. Daca acum se utilizeaza productia A --> a se obtine arborele : S / \ / \ c A d a In acest caz se observa ca sirul va fi in cele din urma acceptat. Exista insa gramatici pentru care daca se utilizeaza transformari. In acest caz indicatorul pe sirul de intrare trebuie sa fie readus in pozitia simbolului a. Xn se va crea o cale intre starea initiala si starea finala cu etichetele X1 X2 . corespunzator trebuie sa se revina cautindu-se o noua varianta pentru A.daca gramatica este recursiva stinga algoritmul poate conduce la aparitia unui ciclu infinit. Analizorul predictiv care lucreaza asupra diagramei de tranzitii . Analiza sintactica predictiva (descendent recursiva) Dezavantajul abordarii anterioare consta in necesitatea revenirilor ceea ce conduce la complicarea deosebita a algoritmilor si mai ales a structurilor de date implicate deoarece automatul push down corespunzator cazului general este nedeterminist. Etichetele arcelor reprezinta atomi lexicali sau simboli neterminali.Implementarea presupune utilizarea unei tehnici cu revenire (backtracking). 3. Fiecare arc etichetat cu un atom lexical indica tranzitia care se executa daca se recunoaste la intrare atomul lexical respectiv. Pentru proiectarea analizoarelor predictive se utilizeaza diagrame de tranzitie.. Pentru arcele corespunzatoare neterminalelor se vor activa procedurile corespunzatoare neterminalelor respective. 2./ \ / a \ b Se poate avansa pe sirul de intrare si in arbore deoarece avem din nou coincidenta simboliilor terminali...1. prin eliminarea recursivitatii stinga si prin factorizare se obtine gramatici care pot sa fie utilizate pentru analiza top-down fara reveniri. Xn. In acest moment se ajunge la compararea simbolului d din sirul de intrare cu simbolul b din arbore. Pentru a construi o diagrama de tranzitie pentru un neterminal A intr-o gramatica in care nu exista recursivitate stinga si in care s-a facut factorizare stinga se procedeaza in modul urmator : 1. pentru fiecare productie A --> X1 X2 . . Din cele prezentate anterior rezulta doua observatii : ..1. In acest caz dindu-se un simbol de intrare si un neterminal exista o singura alternativa de productie prin care din neterminalul respectiv sa se deriveze un sir care incepe cu simbolul de intrare dat.

Daca din starea s exista o ?-tranzitie spre starea t atunci analizorul poate trece direct in stare t fara sa se faca nici o deplasare pe sirul de intrare.13 +----+ +----+ +----+ +----+ +------+ ? ^ +-------------------------------+ F: +----+ ( +----+ E +----+ +------+ ) +----+ .12 --. Se incepe cu starea initiala pentru simbolul de start al gramaticii. E' --> +TE' ?.4 ---.11 ---. F --> (E) a.9 +---+ +---+ +---+ +-----+ T': +----+ +----+ +----+ +------+ * F T' +----+ 10 ----. Diagramele de tranzitie corespunzatoare sint : E: +---+ +---+ +-----+ T E' +---+ 0 ----. Ideea analizei sintactice predictive consta din incercarea permanenta de identificare a simbolului curent de pe banda de intrare cu inceputul unei productii pentru simbolul neterminal curent. Sa consideram de exemplu gramatica pentru expresii aritmetice fara recusivitate stinga : E --> TE'. T --> FT'.functioneaza in modul urmator. Daca se reuseste sa se ajunga la starea finala pentru A se va trece in starea t ( se observa ca in acest caz s-a "citit" A din sirul de intrare).6 +---+ +---+ +---+ +---+ +-----+ ? ^ +---------------------------+ T: +---+ +---+ +-----+ F T' +---+ 7 ----.5 --.2 +---+ +---+ +---+ +-----+ E': +---+ +---+ +---+ +-----+ + T E' +---+ 3 ----. Daca din starea s exista un arc etichetat cu un neterminal A spre starea t atunci analizorul poate sa treaca in starea initiala corespunzatoare neterminalului A fara sa avanseze pe sirul de intrare. T' --> *FT' ?. Daca la un moment dat analizorul se gaseste intr-o stare s din care exista un arc etichetat cu a spre o stare t si simbolul curent de pe sirul de intrare este a E T atunci analizorul se va deplasa pe sirul de intrare cu o pozitie la dreapta si va trece in starea t.8 ---. Acest tip de abordare functioneaza daca diagrama care rezulta este determinista.1 ---.

1 ---. De exemplu observind ca in diagrama de tranzitie pentru E' apare un arc etichetat cu E' se pot face urmatoarele tranformari : E': +------------------------+ V +---+ +---+ +---+ + T ? 3 ----.5 ---+ +---+ +-----+ ? +---+ +-----------------------> 6 +---+ +-----+ +---+ 14 ----.15 ---.16 --- +---+ si apoi E': +---------------+ V +---+ +---+ + T 3 ----. dar acest aspect poate sa fie rezolvat simplu.4 ---+ +-----+ ? +---+ +-----------------------> 6 +---+ +-----+ +---+ +---+ Din E: +---+ +---+ +-----+ T E' +---+ 0 ----. Diagramele de tranzitie obtinute direct din gramatica pot sa fie in continuare simplificate prin citeva transformari simple.2 +---+ +---+ +---+ +-----+ se obtine : E : T +---------------+ . etc. De exemplu pentru E' se va alege in implementare o ?tranzitie daca si numai daca simbolul care urmeaza la intrare nu este +.tranzitiilor care pare sa confere un caracter nedeterminist analizorului sintactic predictiv implementat direct pentru aceste diagrame.17 +----+ +----+ +----+ +----+ +------+ a ^ +-------------------------------+ Acest grup de diagrame de tranzitie prezinta dezavantajul existentei ? .4 ---.

16 --.4 ---+ +---+ +-----+ ? +---+ +-----------------------> 6 +---+ +-----+ +---+ V +---+ +---+ Si apoi pentru ca starile 0 si 4 sint echivalente se obtine : E : + +---------------+ E --> T + E T V +---+ +---+ T 0 ----.+---+ +---+ T + 0 ----.17 +----+ +----+ +----+ +----+ +------+ a ^ +-------------------------------+ Analizorul sintactic corespunzator acestor diagrame de tranzitie este : #include "stdio.h" #include "ctype. /* prototipuri functii */ +----+ +----+ .8 ---+ +---+ +---+ +------+ ? +----+ +-------------> 13 +----+ +------+ F --> (E) a F: +----+ +------+ ( E ) +----+ 14 ----.h" int caracter_curent.3 ----.3 ---+ +---+ +-----+ ? +---+ +-------------> 6 +---+ +-----+ T --> F * T F +---+ T : * +---------------+ V +---+ +---+ F 7 ----.15 ---.

termen(). factor(void). } else break.static static static static void void void void gasit(int t). } /* F --> (E) */ static void factor() { if (caracter_curent == 'a') gasit('a'). T -> T * F T ?. else { gasit('('). while (1) if (caracter_curent == '+') { gasit('+'). termen(void). exit(1). E' --> +TE' */ static void expr() { termen(). factor(). } else { printf("\neroare \n"). } } a ?. expr(void). } /* T --> FT'. gasit(')'). E --> E + T T . expr(). caracter_curent = getchar(). while (1) if (caracter_curent == '*') { gasit('*'). T' --> *FT' */ static void termen() { factor(). static void gasit(int t) { if (caracter_curent == t) { putchar(caracter_curent). } else break. } } /* E --> TE'.

2. Exista trei posibilitati : . Pentru a favoriza construirea unui automat determinist pe banda de intrare sirul ce se analizeaza este urmat de un simbol special care nu apartine gramaticii pe care il vom nota cu $. Stiva contine initial simbolii S si $ unde S este simbolul de start al gramaticii memorat in virful stivei. In momentul in care se gaseste un caracter care nu mai corespunde se afiseaza mesajul de eroare. putchar('\n'). Fie X simbolul din virful stivei si a simbolul curent pe banda de intrare. expr(). Problema fundamentala in timpul analizei predictive consta din determinarea productiei care va fi utilizata pentru neterminalul curent. 3. } Programul afiseaza in ecou caracterele care sint identificate drept corecte. In orice moment stiva contine o secventa de simboli terminali si neterminali. Adica prin simularea explicita a unui automat pushdown. Se observa ca abordarea anterioara presupune utilizarea unor proceduri recursive. conform definitiei de acceptare pentru automate push down deterministe. Programul care simuleaza functionarea analizorului sintactic functioneaza in modul urmator.sintactic ------------> iesire +-----------+ +-----------+ tabela de analiza +-----------+ stiva Se observa ca analizorul este condus de o tabela de analiza care memoreaza functia m a automatului push down.a] unde A este un neterminal iar a este un terminal sau simbolul $. Se poate insa implementa o abordare nerecursiva prin utilizarea unei stive.main() { caracter_curent = getchar(). Gramatici LL(1) In cazul analizei LL(1) modelul analizorului este : banda de intrare ----------------------------------------------------------------^ cap de citire +-----------+ analizor <---------. Tabela de analiza este o matrice M[A. Dezavantajul analizei predictive consta din faptul ca se poate pierde semnificatia productilor ceea ce poate complica pina la imposibil procesul de generare de cod.1.

Avind in vedere ca nu este necesara decit o singura stare pentru unitatea de control a automatului aceasta nu mai este considerata explicit. Yk atunci inlocuieste X din virful stivei cu Y1 Y2 . initializeaza virful stivei intitializeaza pozitie curenta pe banda de intrare repeta fie X simbolul din virful 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... Daca de exemplu M[X. 2.. 3. simbolul X din virful stivei va fi inlocuit cu UVW ( U este noul virf al stivei). daca X = a = $ analiza s-a terminat cu succes..1.a] = {X --> UVW}. derivarea stinga.. analizorul va cerceta valoarea M[X. altfel un mesaj de eroare. Analizorul va afisa productiile aplicate pe masura ce evolueaza. Functionarea analizorului poate sa fie descrisa de urmatorul algoritm de simulare a unui automat push down determinist: Intrare un sir w si o tabela de analiza M pentru gramatica G. Yk afiseaza productia X --> Y1 Y2 . Initial configuratia automatului este w$ pe banda de intrare si S$ in stiva. Valoarea din intrarea respectiva este fie o productie pentru neterminalul X fie o informatie de eroare.. daca X este un neterminal. daca X = a =/ $ analizorul extrage simbolul a din virful stivei si deplaseaza capul de citire pe banda de intrare cu o pozitie la dreapta.a]. Iesire daca w E L(G). Yk altfel eroare = = pina X = $ /* stiva este goala */ Sa reluam exemplul gramaticii expresiilor aritmetice. Tabela de analiza corespunzatoare acestei gramatici este : neterminal a + * ( ) $ ----------+--------+--------+--------+--------+--------+-------E E -> TE' E -> TE' ----------+--------+--------+--------+--------+--------+-------E' E'->+TE' E' --> ? E' --> ? ----------+--------+--------+--------+--------+--------+-------- .a] contine X --> Y1 Y2 .

FIRST : (N U T)+ --> P(T U {?}) FOLLOW : N --> P(T U {$}) Daca w este un sir de simboli w E (N U T)*. FIRST(w) reprezinta setul terminalelor cu care incep sirurile derivate din .T T -> FT' T->FT' ----------+--------+--------+--------+--------+--------+-------T' T'--> ? T'->*FT' T' --> ? T' --> ? ----------+--------+--------+--------+--------+--------+-------F F --> a F->(E) ----------------------------------------------------------------+ Pentru sirul a + a * a rezulta urmatoarele miscari : (stiva este reprezentata cu virful la stinga. deoarece analiza corespunde derivarilor stinga). Stiva Intrare Iesire ------------+-----------------------+---------------------E$ a + a * a $ ------------+-----------------------+---------------------TE'$ a + a * a $ E --> TE' ------------+-----------------------+---------------------FT'E'$ a + a * a $ T --> FT' ------------+-----------------------+---------------------aT'E'$ a + a * a $ F --> a ------------+-----------------------+---------------------T'E'$ + a * a $ ------------+-----------------------+---------------------E'$ + a * a $ T' --> ? ------------+-----------------------+---------------------+TE'$ + a * a $ E' --> +TE' ------------+-----------------------+---------------------TE'$ a * a $ ------------+-----------------------+---------------------FT'E'$ a * a $ T --> FT' ------------+-----------------------+---------------------aT'E'$ a * a $ F --> a ------------+-----------------------+---------------------T'E'$ * a $ ------------+-----------------------+---------------------*FT'E'$ * a $ T'--> *FT' ------------+-----------------------+---------------------FT'E'$ a $ ------------+-----------------------+---------------------aT'E'$ a $ F --> a ------------+-----------------------+---------------------T'E'$ $ ------------+-----------------------+---------------------E'$ $ T' --> ? ------------+-----------------------+---------------------$ $ E' --> ? ----------------------------------------------------------Constructia tabelei de analiza predictiva este realizata cu ajutorul a doua functii FIRST si FOLLOW.

?} FOLLOW(E) = FOLLOW(E') = {). Daca X este un neterminal si X --> Y1 Y2 . Yk este o productie si a E FIRST(Yi). 2. $ face parte gramaticii).). Pentru un neterminal A.*.. Daca X --> ? este o productie atunci FIRST(X) = FIRST(X) U {?} 3.?} FIRST(T') = {*.. Sa consideram aritmetice: din FOLLOW(S) (S este simbolul de start al productie A --> wBB atunci FIRST(B) \ {?} C_ o productie de forma A --> w B sau o --> wBB si ? E FIRST(B) (B ==*> ?) atunci FOLLOW(B) (B poate sa apara si in alte gramatica expresiilor ?. ? E FIRST(Y1).. T' --> *FT' FIRST(E) = FIRST(T) = FIRST(F) = {(. Daca w ==*> ? atunci ? E FIRST(w). 2. ? E FIRST(Yi-1). Xm) toti simbolii diferiti de ? din FIRST(X1). Daca ? E FIRST(Yj). In final daca ? apare in FIRST(Xi). 1 < j < k.. Xm in modul urmator. Pentru a calcula FOLLOW(A) pentru A E N se aplica urmatoarele reguli in mod repetat pina cind nimic nu se mai poate adauga la multimile FOLLOW : 1. Se adauga apoi toti simbolii din FIRST(X2) diferiti de ? daca ? E FIRST(X1). Pentru a calcula FIRST(X) pentru toti simbolii X din gramatica se aplica urmatoarele reguli pina cind nu se mai pot adauga simboli terminali sau ? pentru nici o multime FIRST(X).w... E' --> +TE' F --> (E) a. Daca X este un terminal atunci FIRST(X) = {X}.. Daca Y1 ==*> ? atunci si orice simbol terminal din FIRST(Y2) este inclus in FIRST(X). 3. De exemplu orice simbol terminal din FIRST(Y1) este inclus in FIRST(X). Se adauga la FIRST(X1 X2 . .. Yi-1 ==*> ?) atunci a E FIRST(X). ?. Putem sa calculam acum functia FIRST pentru orice sir X1 X2 . Xm)..$} Construirea tabelei de analiza va utiliza urmatoarele reguli.. atunci ? E FIRST(X).). 1. (Y1 Y2 . 1 < i < m. etc.$} FOLLOW(F) = {+. FOLLOW(A) reprezinta multimea terminalelor a care pot sa apara imediat dupa A intr-o forma propozitionala. de exemplu din nou E --> TE'. T --> FT'.$} FOLLOW(T) = FOLLOW(T') = {+.. Daca exista productie A FOLLOW(A) C_ contexte).. Daca exista o FOLLOW(B). adica daca exista o derivare S ==*> BAat atunci a E FOLLOW(A).. Daca w ==*> ? atunci A este inlocuit in stiva cu w si daca a E FOLLOW(A) (in particular . se adauga ? la FIRST(X1 X2 . Daca A --> w este o productie si a E FIRST(w) atunci analizorul trebuie sa inlocuiasca pe in stiva A cu w daca simbolul pe banda de intrare este a.a} FIRST(E') = {+.

A --> B. Se observa ca gramatica este ambigua si ambiguitatea se manifesta prin alegerea ce trebuie sa fie facuta cind se intilneste simbolul e (else). daca B ==*> ? atunci FIRST(a) n FOLLOW(A) = O/. S' --> e S ?.a] = M[A. E --> b. Rezulta urmatorul algoritm pentru constructia tabelei : initializare matrice M pentru fiecare p = A --> w E P executa pentru fiecare a E FIRST(w) n T executa M[A. Gramaticile LL(1) sint gramatici neambigue. cu a =/ B sint satisfacute urmatoarele conditii : 1. daca a ==*> ? atunci FIRST(B) n FOLLOW(A) = O/. nerecursive stinga si factorizate.a] U {A --> w} = daca ? E FIRST(w) atunci pentru fiecare b E FOLLOW(A) executa /* b E T U {$} */ M[A. Rezulta deci ca gramatica pentru expresii aritmetice este LL(1) S' .e] = {S' --> eS.simbolul a poate sa fie $). S' --> ?} deoarece FOLLOW(S') = {e. FIRST(a) n FIRST(B) = O/ 2.b] U {A --> w} = = = Aplicind acest algoritm asupra gramaticii expresiilor aritmetice va rezulta tabela cu care a fost ilustrata functionarea analizei predictive.b] = M[A. Pentru aceasta gramatica rezulta urmatoarea tabela de analiza : neterminal a b e i t $ ----------+--------+--------+--------+---------+--------+-------S S --> a S->iEtSS' ----------+--------+--------+--------+---------+--------+-------S' -> ? S' --> ? S' -> eS ----------+--------+--------+--------+---------+--------+-------E E --> b -----------------------------------------------------------------+ M[S'. Se poate arata ca o gramatica G este LL(1) daca si numai daca pentru oricare doua productii de forma A --> a. al doilea L pentru utilizarea derivarii stinga (Left). Se observa ca alegerea permanenta a productiei S' --> ? impiedica aducerea terminalului e (else) in virful stivei ceea ce nu poate duce la o evolutie corecta. O gramatica pentru care in tabela de analiza nu exista intrari cu mai multe alternative se spune ca este o gramatica LL(1) (primul L se refera la parcurgerea sirului de intrare de la stinga (Left) la dreapta. Solutia este de a alege productia S' --> eS (aceasta alegere corespunde asocierii cuvintului else cu ultimul then). $}. iar 1 se refera la utilizarea unui singur terminal pentru a adopta o decizie de analiza). Sa consideram urmatoarea gramatica : S --> i E t S S' a.

De exemplu expresiile apar in instructiuni care apar in blocuri care apar in functii. Se observa ca in anumite cazuri (ca in cazul anterior al gramaticii pentru limbajul corespunzator instructiunilor if) se poate face o "potrivire" a matricii M dar nu exista o regula generala de transformare a matricii de analiza astfel incit intrarile multiple sa poata fi inlocuite cu intrari simple. Pe de alta parte in general exista o ierarhie a constructilor sintactice.in timp ce gramatica considerata pentru instructiunea if nu este LL(1). 3.a] = O/). Daca la intilnirea unui astfel de simbol pe banda de intrare se descarca stiva. Aceasta multime se alege astfel incit analizorul sa poata face o revenire rapida pentru erorile cele mai frecvente. 3. etc. Pentru neterminalul A aflat in virful stivei multimea de sincronizare va contine simbolii din FOLLOW(A). O eroare este detectata in timpul analizei daca in virful stivei se gaseste un terminal care nu coincide cu terminalul curent de pe banda de intrare. Transformarea suferita de o gramatica pentru a deveni LL(1) o face insa dificil de recunoscut. 2. etc. Utilizind in caz de eroare daca este posibil pentru neterminalul aflat in virful stivei o ?-productie se poate amina diagnosticarea . Tratarea erorilor in analiza predictiva Existenta in stiva a terminalelor si neterminalelor pe care analizorul se asteapta sa le gaseasca pe banda de intrare simplifica mult problema diagnosticarii erorii.1. Se utilizeaza in acest scop citeva reguli cu caracter euristic ca de exemplu : 1. cuvintele cheie nu fac parte din setul FOLLOW(instructiune). Daca se adauga simbolii din FIRST(A) la multimea de sincronizare pentru A. In acest caz daca dupa o instructiune de atribuire lipseste terminalul care indica terminarea propozitiei in analiza s-ar sari peste cuvintul cheie care reprezinta inceputul instructiunii urmatoare. sau daca pentru neterminalul din virful stivei (fie el A) si terminalul curent de pe banda de intrare (fie el a) in tabela M nu exista o productie (M[A. se vor adauga cuvintele cheie cu care incep instructiunile la multimea de sincronizare pentru neterminalele care genereaza expresii. Solutia este de a transforma (daca se poate) gramatica astfel incit sa devina LL(1). Se pune problema cum se poate realiza o analiza predictiva pentru un limbaj descris de o gramatica care nu este LL(1). exista o buna sansa pentru continuarea analizei. De obicei analiza predictiva este utilizata pentru instructiuni (nu pentru expresii). pentru limbajul C). Rezulta ca multimea de sincronizare corespunzatoare unei structuri sintactice va contine simbolii corespunzatori structurilor superioare.3. Pentru limbaje de programare care au caracter de terminare a instructiunilor (ca de exemplu . Astfel. atunci se poate relua analiza corespunzatoare neterminalului A cu recunoasterea unui terminal din FIRST(A) la intrare. O metoda posibila de continuare in caz de eroare consta din ignorarea de pe banda de intrare a simbolilor care urmeaza pina la intilnirea unui simbol dintr-o multime numita multime de sincronizare.

4. a + * ( ) $ sinc ----+--------+--------+--------+------+--------+--------+-----E E -> TE' E->TE' sinc sinc ) $ ----+--------+--------+--------+------+--------+--------+-----E' E'->+TE' E' --> ? E' --> ? ) $ ----+--------+--------+--------+------+--------+--------+-----T T -> FT' sinc T->FT' sinc sinc + ) $ ----+--------+--------+--------+------+--------+--------+-----T' T'--> ? T'->*FT' T' --> ? T' --> ? + ) $ ----+--------+--------+--------+------+--------+--------+-----F F --> a sinc sinc F->(E) sinc sinc +*)$ ---------------------------------------------------------------+ Multimile sinc sint construite pornind de la functia FOLLOW.a] = sinc atunci se descarca virful stivei pentru a continua analiza cu ce urmeaza dupa simbolul din virful stivei. Daca pentru terminalul din virful stivei nu exista o corespondenta in sirul de intrare se poate anunta un mesaj corespunzator renuntindu-se la simbolul respectiv. Daca M[A. Utilizind functiile FIRST si FOLLOW se poate completa tabela M cu informatiile referitoare la multimea simbolilor de sincronizare. Cu ajutorul unei tabele de acest tip analiza se va executa in modul urmator .a] nu contine nici o valoare atunci se avanseaza peste simbolul curent (a).erorii. Daca M[A. ) E/ FIRST(E) ------------+-----------------------+---------------------TE'$ a * + a $ E --> TE' ------------+-----------------------+---------------------FT'E'$ a * + a $ T --> FT' ------------+-----------------------+---------------------aT'E'$ a * + a $ F --> a ------------+-----------------------+---------------------T'E'$ * + a $ ------------+-----------------------+---------------------*FT'E'$ * + a $ T' --> *FT' ------------+-----------------------+---------------------FT'E'$ + a $ eroare ------------+-----------------------+---------------------T'E'$ + a $ T' --> ? ------------+-----------------------+---------------------E'$ + a $ E' --> +TE' ------------+-----------------------+---------------------+T'E'$ + a $ ------------+-----------------------+---------------------T'E'$ a $ T'--> ? ------------+-----------------------+---------------------E'$ $ E' --> ? ------------+-----------------------+---------------------- . Daca terminalul din virful stivei nu se potriveste cu terminalul de la intrare se descarca terminalul din virful stivei. De exemplu pentru secventa de intrare : )a * + a se obtine : Stiva Intrare Iesire ------------+-----------------------+---------------------E$ ) a * + a $ eroare.

localizarea capatului. Din sirul de intrare se muta simboli terminali in stiva pina cind in virful stivei se obtine un capat care este redus la partea stinga a uneia dintre productiile corespunzatoare gramaticii. 3. Algoritmul de analiza sintactica de tip deplaseaza si reduce realizeaza simularea unui automat push down utilizind o stiva si un vector de intrare. 2.2. alegerea productiei (daca exista mai multe productii cu aceeasi parte dreapta). Implementarea analizei sintactice bottom-up deplaseaza reduce Utilizind metoda "handle pruning" trebuie sa fie rezolvate doua probleme : 1.1. 3.2. stiva intrare actiune -------------------+------------------+-------------------$ a + a * a $ deplaseaza -------------------+------------------+-------------------$a + a * a $ reduce E -> a -------------------+------------------+-------------------$E + a * a $ deplaseaza -------------------+------------------+-------------------$E + a * a $ deplaseaza -------------------+------------------+-------------------$E + a * a $ reduce E -> a -------------------+------------------+-------------------$E + E * a $ deplaseaza -------------------+------------------+-------------------$E + E * a $ deplaseaza -------------------+------------------+-------------------$E + E * a $ reduce E -> a -------------------+------------------+-------------------$E + E * E $ reduce E -> E * E -------------------+------------------+-------------------$E + E $ reduce E -> E + E .$ $ ----------------------------------------------------------Se observa ca pentru inceput se cauta un simbol din FIRST(E) pentru a incepe recunoasterea ignorindu-se astfel terminalul ) si nu se descarca stiva.2. Analiza sintactica bottom-up 3. Analiza sintactica de tip deplaseaza si reduce Analiza sintactica de tip bottom-up incearca sa construiasca un arbore de derivare pentru un sir de intrare dat pornind de la frunze spre radacina aplicind metoda "handle pruning".+] = sinc se va descarca stiva. Pentru M[F.2. Sa consideram de exemplu actiunile necesare pentru recunoasterea sirului a + a * a pentru gramatica expresiilor aritmetice : E --> E + E E * E a. Daca initial in stiva se gaseste numai simbolul $ iar pe banda de intrare se gaseste sirul w$ in final daca w apartine limbajului acceptat de analizor in stiva se va gasi $S (cu S virful stivei) iar pe banda de intrare capul de citire este pozitionat pe simbolul $.

x.presupune mutarea terminalului curent de pe banda de intrare in virful stivei. deplasare . Avantajul utilizarii stivei consta din faptul ca un capat se formeaza intodeauna in virful stivei (si deci daca nu s-a format in virful stivei un capat atunci acesta nu trebuie sa fie cautat in alta parte). reduce . 2. A --> y. succes . a. eroare.B. S ==> a B x A z ==> a B x y z ==> a t x y z cu A --> B B y. 3.t E (T U N)+ * In primul caz ( S ==> a A z) reducerea inseamna : stiva $aBt $aBB $aBBy $aA $aAz $S intrare yz$ yz$ z$ z$ $ se se se se se reduce t copiaza y reduce BBy copiaza z reduce aAz * In al doilea caz ( S ==> a B x A z). S ==> a A z ==> a B B y z ==> a B t y z * * * 2.z E T*. Sa consideram doua situatii care pot sa apara in cazul derivarilor dreapta : * * * 1. Setul prefixelor derivarilor dreapta ce pot sa apara in virful stivei in analiza unui analizor de tip deplaseaza reduce se numeste setul prefixelor viabile pentru gramatica respectiva. deoarece se poate ajunge fie in situatii in care nu se stie daca trebuie sa . Exista gramatici independente de context pentru care nu se poate utiliza o analiza de tip deplaseaza si reduce. B --> t. stiva $at $aB $aBx $aBxy $aBxA $aBxAz $S intrare xyz$ xyz$ yz$ z$ z$ $ se se se se se se reduce t copiaza x copiaza y reduce y copiaza z reduce aBxAz Se observa ca intodeauna capatul utilizat pentru reducere este in virful stivei. 4.in virful stivei se gaseste un capat care va fi inlocuit cu partea stinga a productiei respective.s-a ajuns la capatul sirului si continutul stivei este $S.-------------------+------------------+-------------------$E $ succes ----------------------------------------------------------Se observa ca exista 4 tipuri de operatii : 1.y.

Sa consideram ca analizorul lexical produce pentru atomul lexical identificator simbolul terminal id. O solutie consta din modificarea analizorului lexical care poate sa furnizeze doua terminale corespunzatoare variabilelor indexate si numelor de functii.se efectueze o deplasare sau o reducere (conflict reducere / deplasare) respectiv nu se stie care dintre variantele de reducere posibile trebuie sa fie luata in considerare (conflict reduce / reduce).j) si deci care este de forma id(id...id). pe baza modului in care se realizeaza derivarile dreapta. Sa definim asupra multimii N U T trei relatii >.2. Fie o derivare dreapta de forma : . Aceasta gramatica si in general orice gramatica ambigua nu permite o analiza sintactica bottom . in forma ambigua : instr --> if expresie then instr if expresie then instr else instr alte_instr Daca se ajunge in configuratia : stiva . Sa observa ca in acest caz avem un conflict deplaseaza / reduce. $ nu putem sa hotarim daca if expresie then instr este un capat indiferent de ce mai contine stiva. Aceasta informatie poate sa fie cunoscuta din tabela de simboli. Se obtine urmatoarea gramatica : instructiune --> id(lista_par) expresie := expresie lista_par --> lista_par. Sa consideram si o gramatica care descrie instructiuni de atribuire si apeluri de functii. Gramatici de precedenta cu operatori Gramaticile de precedenta sint gramatici pentru care se implementeaza usor algoritmul de analiza de tip deplasare / reducere. = si <. In acest caz alegerea reducerii se va face in functie de tipul identificatorului care precede paranteza. Pentru acest caz particular daca hotarim ca in situatia unui conflict deplaseaza / reduce are prioritate deplasarea atunci se va ajunge la o executie corecta a analizei. Se observa ca se ajunge in configuratia: stiva id ( id intrare .. Sa consideram de exemplu din nou gramatica pentru instructiuni. 3..up determinista.3. In expresiile care apar in instructiunea de atribuire si in lista de parametri actuali ai unei proceduri pot sa apara variabile simple sau elemente de variabilele indexate pentru care se utilizeaza paranteze obisnuite.if expresie then instr intrare else .. id id expresie --> id(lista_expr) id lista_expr --> lista_expr. id ) .. expresie expresie Sa consideram o instructiune care incepe cu A(i. Se observa ca nu se stie care este productia cu care se face reducerea pentru ca simbolul neterminal la care se face reducerea depinde de tipul variabilei A (variabila indexata sau functie).

In acest caz relatia > este definita astfel incit intre cel mai din dreapta simbol din t (terminal sau neterminal) si primul simbol din B (terminal) exista relatia >. B E T* (A este cel mai din dreapta neterminal din forma propozitionala a A B). a E T* atunci X > $.productii 2. A doua abordare pleaca de la o gramatica obtinuta prin transformarea gramaticii initiale in care se pun in evidenta proprietatiile de asociativitate si prioritatile relative ale operatorilor. Relatia < este definita astfel incit intre ultimul simbol din a (terminal sau neterminal) si primul simbol din t (terminal sau neterminal) exista relatia <. Exista mai multe moduri de construire a relatiilor de precedenta dupa cum exista si mai multe tipuri de realatii de precedenta. X E N U T. Pentru a simplifica analiza se considera ca pe sirul de analizat este cuprins intre doua caractere $. O gramatica de precedenta cu operatori este o gramatica independenta de context care satisface urmatoarele conditii : 1. a E T. A. dar ramine situatia unor operatori care pot functiona atit ca operatori unari cit si ca operatori binari. In acest caz exista doua moduri de stabilire a relatiilor care exista intre doua terminale. Daca exista o derivare S ==+> a X. Se observa ca aceste relatii rezolva problema ambiguitatii. B E N (2) X = Y daca exista o productie A --> a X Y B E P (3) X > a daca exista o productie A --> a B Y B E P si B ==+> tX. X E (N U T). a E T* atunci $ < X. De exemplu relatiile de precedenta pot sa fie stabilite pe baza regulilor Wirth . De exemplu daca dorim sa obtinem relatiile de . In acest caz se spune ca gramatica este de precedenta. In cazul gramaticilor de precedenta cu operatori relatiile de precedenta se pot considera numai asupra terminalelor. Y E N U T. Rezulta deci ca pe baza acestor relatii devine simpla identificarea capetelor daca intre oricare doi simboli din N U T are loc cel mult una dintre relatii. t E (N U T)* . nu exista ? . Prima metoda este intuitiva si se bazeaza pe relatiile de asociativitate si precedenta. X.E E * E E / E E ^ E (E) -E a In general gramaticile de precedenta si analiza sintactica care se bazeaza pe acest tip de gramatici sint utilizate pentru realizarea analizei sintactice a expresiilor dintr-un limbaj de programare. nu exista productii care au in partea dreapta siruri care contin doua neterminale adiacente. Un exemplu de gramatica de precedenta cu operatori este gramatica expresiilor aritmetice : E --> E + E E . Pentru oricare pereche de simboli din t exista relatia =.S ==+> a A B ==+> a t B cu a. Adica un caracter este initial in stiva iar al doilea urmeaza dupa sirul de analizat la intrare. In acest caz daca exista o derivare S ==+> X a.Weber : (1) X < Y daca exista o productie A --> a X B B E P si B ==+>Yy. Y ==*> a w. Un caz particular de gramatica de precedenta este gramatica de precedenta cu operatori. Astfel + < * si * > +.

a E t E N U {?}. a E (N U T)*. Sa presupunem ca intre ai si ai+1 are loc numai una dintre cele trei relatii. Se observa ca $ < b si b > $ pentru orice terminal b E T. a. se obtine : $ < a > + < a > * < a > $ gasirea capatului decurge in modul urmator : 1. F --> o gramatica cu operatori : (1) a = b daca exista o productie A --> a a N U {?}. se parcurge sirul de la stinga la dreapta pina la prima realatie >.0 <= i <= n. se obtine tabela de precedenta : a + * $ -----+---+---+---+--a > > > -----+---+---+---+--+ < > < > -----+---+---+---+--* < > > > -----+---+---+---+--$ < < < ---------------------+ Relatile de precedenta sint utilizate pentru identificarea capatului unei forme propozitionale dreapta. se merge inapoi pina la intilnirea unei relatii <. Sa presupunem ca fiecare neterminal dintr-o forma propozitionala a fost eliminat si sa introducem intre terminalele ramase relatia corespunzatoare. Se observa ca din conditia impusa asupra gramaticii orice productie este de forma B0 a1 B1 . De exemplu pentru gramatica E --> E + T T. t E N U {?} (3) a > b daca exista o productie A --> a B w a t. (N U T)* t b B E P cu t E a a B B E P. De exemplu pentru forma propozitionala a + a * a.precedenta pentru gramatica E --> E + gramatica transformata : E --> E + T a. a E Daca intre doua terminale exista cel mult o relatie atunci gramatica este de precedenta cu operatori. b B E P si B ==+> t E N U {?}. Initial stiva contine simbolul $. Pe banda de intrare se gaseste w$. t E N U {?}. 1 < i < n.. . Relatiile de precedenta pentru se obtin utilizind urmatoarele reguli E E * E a se va utiliza T. Deoarece neterminalele nu influenteaza evolutia analizei nu este nevoie sa se faca o diferentiere intre ele (ceea ce este echivalent in cazul nostru cu revenirea la gramatica in care nu au fost evidentiate proprietatile operatorilor). (N U T)* (5) a > $ daca exista o derivare S =*> aat. T --> T * F F. cu < delimitind inceputul.. an Bn unde Bi E N U {?} . F --> a. = parcursul si > sfirsitul capatului. B E (N U T)* (2) a < b daca exista o productie A --> B ==+> t b w. ai E T. T --> T * F F. (4) a < $ daca exista o derivare S =*> taa. 2.

Nu este cazul daca simbolii care au fost deja parcursi sint copiati in stiva si relatiile de precedenta comanda functionarea analizorului. Continuind la un moment dat se ajunge la forma propozitionala E + E * E. Daca operatorul o1 are prioritate mai mare decit o2.4. Aparent la fiecare pas trebuie analizata intreaga forma propozitionala dreapta. In general algoritmul de analiza care parcurge si verifica buna formare a propozitiei poate sa fie descris in modul urmator : initializeaza stiva initializeaza pozitia curenta in sirul de intrare repeta daca $ este in virful stivei si simbolul curent pe banda de intrare este $ atunci succes & return altfel fie a terminalul din virfuk stivei fie b terminalul curent de pe banda de intrare daca a < b sau a = b atunci push b /* deplasare */ avans pe banda de intrare altfel daca a > b /* reduce */ atunci repeta descarca stiva pina cind terminalul din virful stivei este in relatia < cu precedentul terminal extras din stiva altfel eroare & return = = = pina false 3. Stergind din nou neterminalele si inlocuindu-le cu relatii se obtine : $ < + < a > * < a > $.3. Daca intre terminalul aflat in virful stivei si simbolul curent de pe banda de intrare exista relatia = sau < atunci se va executa o deplasare. Relatii de precedenta stabilite pe baza proprietatilor de asociativitate si prioritatile operatorilor Pentru limbajele de tipul limbajului pentru expresii aritmetice (E --> E + E E * E (E) a) se pot utiliza o serie de reguli euristice care permit selectia capetelor conform proprietatilor de prioritate si asociativitate : 1. Se observa ca urmeaza sa se reduca urmatorul a. Se obtine acum $ < + < * > $. Daca relatia este > se va executa o reducere. . Rezulta capatul E * E. In exemplul considerat primul capat este a. rezulta forma propozitionala E + a * a.2. capatul este format din simbolii cuprinsi intre cele doua relatii fixate (< si >) inclusiv neterminalele continute intre terminalele corespunzatoare inceputului si sfirsitului de capat. Daca nu exista nici o relatie atunci a fost detectata o eroare sintactica si trebuie sa fie activata o procedura de tratare a erorilor. In acest caz inceputul capatului este intre + si * iar sfirsitul este intre * si $.

o > $ si $ < o (pentru orice o operator).E. astfel incit pentru E ^ E ^ E se va selecta intii ultima ridicare la putere.> . * si / sint operatori asociativi stinga. Probleme deosebite apar daca acelasi semn este utilizat atit ca operator unar cit si ca operator binar. Daca o1 si o2 au aceasi prioritate (poate sa fie vorba si de acelasi operator) atunci o1 > o2 si o2 > o1 daca operatorul este asociativ stinga respectiv o1 < o2 si o2 < o1 daca operatorul este asociativ dreapta.au prioritatea cea mai mica si sint operatori asociativi stinga. 3. In acest mod in expresia E + E * E + E capatul E * E va fi redus intii 2. De asemenea exista urmatoarele relatii : ( = ) ( < ( ( < a $ < ( a > $ a > ) $ < a ) > $ ) > ) Aceste reguli asigura reducerea capetelor a si (E) la E. o < ( . ^ este operatorul cu prioritatea cea mai mare si este un operator asociativ dreapta. . o > ).> + daca + si .sint operatori asociativi stinga. In cazul in care pentru operatia operatia de ridicare la putere se considera asociativa dreapta atunci ^ < ^. Pentru exemplul considerat * > + si + < *.* / ^ a ( ) $ ---+---+---+---+---+---+---+---+---+--+ > > < < < < < > > ---+---+---+---+---+---+---+---+---+--. In acest caz pentru E .( < o.atunci o1 > o2 si o2 < o1. + si . operator < operand. 4. O solutie ar fi ca analizorul lexical sa furnizeze atomi lexicali diferiti pentru . sirul poate sa inceapa cu ( sau a si se poate termina cu ) sau cu a. De exemplu + > +. De exemplu pentru operatorii aritmetici obisnuiti se obtine : + . intre operanzi si operatori exista relatiile operand > operator. + > -.si .> > < < < < < > > ---+---+---+---+---+---+---+---+---+--* > > > > < < < > > ---+---+---+---+---+---+---+---+---+--/ > > > > < < < > > ---+---+---+---+---+---+---+---+---+--^ > > > > < < < > > ---+---+---+---+---+---+---+---+---+--a > > > > > > > ---+---+---+---+---+---+---+---+---+--( < < < < < < < = ---+---+---+---+---+---+---+---+---+--) > > > > > > > ---+---+---+---+---+---+---+---+---+--$ < < < < < < < ---------------------------------------+ pentru ca : 1. 2.E + E se va selecta intii E . ) > o. De asemenea $ reprezinta atit un indicator de inceput cit si de sfirsit de sir de intrare. 3.

Deoarece analizorul lexical nu are acces la informatia care urmeaza pe banda de intrare. n2 indica faptul ca "valoarea de precedenta" a nodului n1 trebuie sa fie mai mare decit a nodului n2. f(a) < g(b) 2. Functii de precedenta In analizoarele sintactice se lucreaza nu cu tabelele de precedenta ci cu functii de precedenta prin care se asigneaza atomilor lexicali valori numerice si care asigura prin relatiile dintre ele relatiile dintre atomii lexicali respectivi. Se observa insa ca in aceste situatii in virful stivei nu se construieste un capat ceea ce permite diagnosticarea erorii respective. Si anume se considera doua functii f si g astfel incit daca a si b sint atomi lexicali atunci : 1. 3. o virgula sau un operator de atribuire. In acest caz. decizia trebuie sa fie luata pe baza informatiei precedente.cele doua situatii de utilizare a operatorului respectiv.* / ^ ( ) a $ ---+---+---+---+---+---+---+---+---+--f 2 2 4 4 4 0 6 6 0 ---+---+---+---+---+---+---+---+---+--g 1 1 3 3 5 5 0 5 0 ---------------------------------------+ O metoda de construire a functiilor de precedenta pentru o tabela de precedenta data este data de urmatorul algoritm : Intrare o matrice de precedenta Iesire daca exista o solutie se obtin functiile f si g. intrari care semnifica situatii de eroare nu pot sa fie identificate prin valorile functiilor f si g. o paranteza deschisa. Pentru orice a si b daca a < b se construieste un arc orientat de la grupul care contine simbolul g(b) la grupul care contine simbolul f(a). se construieste un graf orientat ale carui noduri reprezinta grupurile stabilite in pasul anterior. Daca a > b se construieste un arc de la grupul care il contine pe f(a) la grupul care contine g(b). . f(a) > g(b) daca a < b daca a = b daca a > b Se observa ca functia f reprezinta "valoarea de prioritate" stinga respectiv g reprezinta "valoarea de prioritate" dreapta. se impart multimiile f(a) si g(a) in grupuri pe baza relatiei = (daca a = b atunci f(a) si g(b) sint in acelasi grup). daca nu exista solutie. Un arc intre nodurile n1. f(a) = g(b) 3.va fi considerat ca operator unar daca urmeaza dupa un operator. o informatie corespunzatoare. intrarile nedefinite in tabela de precedenta. Pentru tabela care contine toate operatiile aritmetice o solutie de valori pentru functiile f si g este : + . pentru fiecare a E T executa creaza simbolii f(a) si g(a) = 2. astfel ca intr-un limbaj de programare semnul . 1.

contine nodurile care prin tranzitivitate trebuie sa aiba o "valoare de precedenta" mai mica. dreapta.detectarea erorilor sintactice se face foarte aproape de atomul lexical in legatura cu care a aparut eroare. Aceasta regula porneste de la observatia ca pentru un nod aceasta cea mai lunga cale. Sa consideram din nou structura unui automat pushdown.5. Analiza sintactica de tip LR(k) LR(k) este o metoda de analiza al carui nume are urmatoarea semnificatie : primul L indica sensul parcurgerii . Rezulta : + * a $ ---+---+---+---+--f 2 4 4 0 ---+---+---+---+--g 1 3 5 0 -------------------+ 3.tehnica LR este cea mai cunsocuta metoda de tip deplaseaza si reduce.stinga. litera R indica faptul ca derivarea este dreapta iar k indica numarul de atomi lexicali necesari pentru o alegere corecta a unui capat din stiva. Avantajele metodei LR(k) sint : . .g$ <--+ +---+ +---+ Nu exista cicluri deci se pot calcula functiile de precedenta. . Dezavantajul major al acestei metode . daca graful orientat contine cicluri atunci nu se pot construi functii de precedenta.4.ga \ +---+ \ +---+ fa ---+ /+---+ se \ / +-V-+ \ / +-V-+ f* ----\-------/--> g* +---+\ ---\-----/ /+---+ / \ / +-V-+/-\ \------->+-V-+ g+ <--\--------/--.clasa limbajelor care pot sa fie analizate predictiv este o submultime proprie a limbajelor care pot sa fie analizate prin tehnici LR.se pot construi analizoare de tip LR pentru aproape toate constructiile din limbajele de programare care pot sa fie descrise de gramatici independente de context.\ +-V-+ --------->+-V-+ +--> f$ <--------------.volumul mare de calcul necesar pentru implementarea unui astfel de analizor fara aportul unui generator automat de analizoare sintactice. .2.f+ +---+ ---\------/ +---+ /. De exemplu pentru gramatica expresiilor aritmetice obtine: +---+ +--. Daca nu exista cicluri atunci f(a) (g(a)) este lungimea celei mai lungi cai care pleaca din grupul care il contine pe f(a) (g(a)). .

In cazul analizei de tip LR(k) se utilizeaza pentru identificarea capetelor un automat finit. Si anume se numeste capat al unei forme propozitionale partea dreapta a unei productii care daca este inlocuita cu partea stinga produce forma propozitionala anterioara in sirul formelor propozitionale obtinute intr-o derivare dreapta.banda de intrare ----------------------------------------------------------------^ cap de citire +-----------+ analizor <---------.sintactic ------------> iesire +-----------+ +-----------+ tabela de analiza +-----------+ In cazul analizei LR functia de tranzitie (m) este descrisa intro tabela de analiza care este formata din doua parti (actiuni si goto). Evident simulatorul automatului push down care reprezinta de fapt programul de analiza propriu-zis nu se modifica de la un limbaj la altul. Rolul acestui automat este de a controla activitatea de recunoastere a capetelor. Ceea ce se schimba este tabela de analiza. o astfel de abordare este ineficienta. Evident. Inainte de a incepe discutia referitoare la modul de construire a tabelelor de analiza este bine sa reamintim citeva definitii. Dupa cum s-a constatat si in cazul analizei sintactice realizata pe baza gramaticilor de precedenta problema centrala consta din identificarea momentului in care in virful stivei a fost obtinut un capat. Desigur o varianta posibila este explorarea completa a stivei la fiecare pas. Sa consideram de exemplu gramatica expresiilor aritmetice : (1) (2) (3) (4) (5) (6) E E T T F F --> --> --> --> --> --> E + T T T * F F (E) a Putem sa consideram diagrama de tranzitii corespunzatoare acestor productii: +----+ E ----> +------+ T +----+ I1 I6 ----> I9 +----+ +------+ +------+ +------+ +------+ +------+ +-------+ T +----+ * F +-----+ ----> I2 ----> I7 ----> I10 +----+ +-----+ + ----> +------+ +------+ . Un prefix viabil este un subsir cu care incepe o forma propozitionala.

+----+ .+------+ +------+ +-------+ +------+ F +----+ I0 ----> I3 +----+ +------+ +------+ +------+ +-------+ ( E ) +-----+ ----> I4 ----> I8 ----> I11 +-----+ +------+ +------+ +-------+ +------+ a +----+ ----> I5 +----+ +------+ +----+ Sa urmarim secventa de stari prin care se trece pentru sirul de intrare a * a + a. cu alte cuvinte sirul de intrare este de forma F * a + a (deplasare pentru a. cu alte cuvinte sirul de intrare este de forma T * a + a (reducere pentru T --> F) +------+ I7 +------+ +------+ +------+ a +----+ a fost recunosI7 ----> I5 cuta in starea 7 +----+ partea dreapta a +------+ +------+productiei F --> a in acest moment la intrare urmeaza a + a Cu alte cuvinte in starea 7 urmeaza sirul de intrare F + a +------+ +------+ +------+ +------+ T * F +----+ I0 ----> I2 ----> I7 ----> I10 +----+ +------+ +------+ +------+ +------+ A fost recunoscuta in starea 0 partea dreapta a productiei T --> T * F (reducere). +------+ +------+ a +----+ I0 ----> I5 +----+ +------+ +------+ +------+ +------+ F +----+ I0 ----> I3 +----+ +------+ +------+ +------+ I0 +------+ +------+ I0 +------+ T ----> T ----> +------+ I2 +------+ +------+ I2 +------+ * ----> * ----> a fost recunoscuta in starea 0 partea dreapta a productiei F --> a. ----> I2 la intrare urmeaza sirul + a. +------+ I0 +------+ a fost recunoscuta in starea 0 partea T +----+ dreapta a productiei E --> T. urmata de reducere cu F --> a) a fost recunoscuta in starea 0 partea dreapta a productiei T --> F.

( \ / +-------+ ( +----+ E +----+ ) +-----+ ----> I4 -----> -----> I11 +----+ +-----+ \\ I8 + +-------+ a \\ T -----> I6 V \\ +------+\\ +----+ +------+ .+------+ +------+ I0 +------+ E ----> +------+ +------+ I1 +------+ + ----> +------+ +------+ a +----+ a fost recunosI6 ----> I5 cuta in starea 6 +----+ partea dreapta a +------+ +------+productiei F --> a Evolutia continua pina la obtinerea situatiei : +------+ I0 +------+ E ----> +------+ I1 +------+ Avind in vedere aceasta evolutie diagrama de tranzitii poate sa fie reprezentata si sub forma urmatoare (in care se evidenteaza toate capetele care pot sa apara) : +----+ E ----> +------+ + +----+ T +----+ * I1 -----> -----> I9 -----> I7 +----+ +------+ +------+ F I6 -----> I3 ( -----> I4 a -----> I5 +----+ +------+ +-------+ T +----+ * +----+ F +-----+ ----> I2 -----> -----> I10 +----+ +-----+ +------+ I7 +-------+ ( ------> I4 I0 a ------> I5 +------+ +----+ F +----+ ----> I3 +----+ +------+ .

a] poate avea urmatoarele valori : 1. a. Simbolii Xi reprezinta simboli din gramatica iar si reprezinta stari ale automatului care recunoaste capete. goto[si. Un analizor sintactic LR realizeaza simularea acestor recunoasteri de capete memorind in stiva starile prin care se trece intr-o recunoastere ca cea facuta anterior. eroare Pentru o combinatie (si. Xi E N. Dupa T se gaseste la intrare * apoi a.I2 ----> I5 \ +----+ \ F +----+ +------+ \. Sa urmarim secventa de stari prin care se poate trece pentru sirul de intrare a * a + a : a 0 -----------> 5 \\\ F \\ --------> 3 \\ T * a \--------> 2 ------> 7 -------> 5 \ \ F \ -------> 10 \ E + a -----> 1 ------> 6 -------> 5 \\ F \-------> 3 \ T ------> 9 Se observa ca pentru primul simbol a se ajunge in starea 5 in care s-a recunoscut partea dreapta a productiei F --> a. Continutul stivei la un moment dat este de forma s0 X1 s1 X2 s2 . similar in acest caz s-a recunoscut partea dreapta a productiei T --> F. Xi). 2. Xn sn. Pe baza informatiei specificate de starea din virful stivei si a simbolului curent de pe banda de intrare se determina miscarea urmatoare efectuata de catre analizor. In acest moment in starea 10 s-a citit la intrare sirul T * F deci se poate aplica pentru reducere productia T --> T * F. actiune[sn. este ca si cum s-ar fi aplicat la intrare sirul F * a + a. reduce pe baza productiei A --> B.I3 Se utilizeaza conventia ca la fiecare reducere se revine in starea anterioara lantului de arce corespunzatoare capatului identificat executindu-se o noua tranzitie. noua stare find determinata din tabela goto. unde virful stivei este sn ( de fapt in stiva este suficient sa se memoreze numai starile si nu si simboli Xi). deplasare in starea s (se copiaza terminalul curent de pe banda de intrare in stiva si se trece in starea s). 3.. Configuratia unui analizor LR este formata din continutul stivei si cel al benzii de intrare. Deoarece pe tot parcursul . Tabela de analiza este formata din doua parti : tabela de actiuni si tabela goto.Xi] este o stare a automatului care recunoaste capete. succes 4. ajungindu-se in starea 5 in care se recunoaste din nou partea dreapta a productiei F --> a..a +----+ \\. Desenul anterior poate sa fie interpretat ca reprezentind un automat finit care recunoaste capete. Pentru o combinatie sn.

o propozitie derivata in G atunci se productiilor aplicate intr-o derivare se obtine un mesaj de eroare noua pozitioneaza ip pe inceputul sirului w$ si s0 in stiva. se obtine configuratie : (s0 X1 s1 X2 . Xm sm. ai+1 . aceasta nu mai este prezentata explicit.. altfel corespunzator. an$) unde s = goto[sm-r.. si o tabela de analiza LR.. A]).. 3..a] = reduce A --> B atunci extrage 2 * B simboli din stiva fie s' noul virf al stivei memoreaza A in stiva memoreaza goto[s'. an$) unde X1 X2 .. Xm ai ai+1 . an reprezinta o forma propozitionala obtinuta dintr-o derivare dreapta daca sirul aflat initial pe banda de intrare face parte din limbaj. starea noua din virful stivei fiind sm-r.. Deci o configuratie este de forma : (s0 X1 s1 X2 ..ai] = acc atunci analiza se incheie. Modificarile posibile pentru configuratia automatului pot sa fie : 1. Se observa ca s-au eliminat 2 * r simboli din stiva.. daca actiune[sm. repeta fie s simbolul din virful stivei si a simbolului de intrare curent daca actiune[s. ai ai+1 .ai] = deplasare s. daca actiune[sm. Se introduce apoi in stiva neterminalul A (partea stinga a productiei) si starea obtinuta pentru sm-r si A din tabela goto (s = goto[sm-r. an$) 2..analizei automatul push down se gaseste in aceasi stare.. daca actiune[sm. daca actiune[sm. ai ai+1 ..a] = deplaseaza s' atunci memoreza a si s' in stiva ip++ altfel daca actiune[s.ai] = reduce pe baza A --> B.A] in stiva afiseaza productia A --> B altfel .A] iar r este lungimea capatului B utilizat pentru reducere. 4. Xm sm ai s. Xm-r sm-r A s .. Urmatoarea miscare a analizorului depinde de ai si sm si este descrisa de actiune[sm.ai] = eroare inseamna ca s-a diagnosticat o eroare..ai].. se obtine configuratia : (s0 X1 s1 X2 . Algoritmul general de analiza LR este : Intrare un sir de intrare w Iesire daca w E L(G) este va obtine o lista a dreapta..

a] = acc atunci return altfel eroare = = = pina false Sa consideram de exemplu pentru gramatica : (1) (2) (3) (4) (5) (6) E E T T F F --> --> --> --> --> --> E + T T T * F F (E) a si tabela de analiza: actiune goto si .a] este continuta in tabela actiune[X. Sa consideram sirul de intrare a * a + a stiva intrare actiune ---------------+------------+----------------------------------0 a * a + a $ deplasare .a] pentru a E T.daca actiune[s.reprezinta deplasare si starea urmatoare i rj .reprezinta eroare stare a + * ( ) $ E 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 -------------------------------------------+ Tabela goto[X.reprezinta succes blanc .reprezinta reducerea cu productia j acc .

goto[7. Un element LR(0) pentru o gramatica G este o productie avind un punct intercalat intre simbolii partii dreapta ai productiei. [A --> X. Simbolii de stare din stiva reprezinta de fapt starile unui astfel de automat.YZ]. Productia A --> ? produce un singur element [A --> . Analiza SLR Cea mai simpla metoda de construire a tabelelor de analiza LR este metoda SLR (simple LR). goto[0. goto[6. pentru analiza LR(k) este cunoscuta partea dreapta a productiei si trebuie "ghicita" productia pe baza urmatorilor k atomi lexicali care urmeaza. Se observa ca deosebirea fundamentala intre analiza LL si analiza LR este ca pentru analiza LL(k) pe baza a k atomi lexicali trebuie "ghicita" productia care se poate aplica.evolutia analizorului urmareste recunoasterea capatului din virful stivei automatului push down. 3. In cele ce urmeaza prezentam citeva metode de construire a tabelelor de analiza pentru analiza LR(1).E]=1 ---------------+------------+----------------------------------0 E 1 + a $ deplaseaza ---------------+------------+----------------------------------0 E 1 + 6 a $ deplaseaza ---------------+------------+----------------------------------0 E 1 + 6 a 5 $ reduce cu F --> a (6).F]=10 ---------------+------------+----------------------------------0 T 2 * 7 F 10 + a $ reduce cu T --> T * F (3) ---------------+------------+----------------------------------0 T 2 + a $ reduce cu E --> T (2).Z]. al doilea numar este pozitia punctului.]. Se poate face urmatoarea observatie .]. Ideea utilizarii acestor elemente este ca pentru a se recunoaste capatul XYZ se vor aduce pe rind in virful stivei prefixele X.2. goto[0. In acest mod informatia din virful stivei codifica de fapt tot ce se gaseste in stiva din punctul de vedere al capatului construit. goto[0. [A --> XY.1. XYZ.---------------+------------+----------------------------------0 a 5 * a + a $ reduce cu F --> a (6). [A --> XYZ. XY. Primul reprezinta numarul productiei.XYZ]. Semnificatia unui element este cit s-a recunoscut (vazut) din partea dreapta a unei productii.F]=3 ---------------+------------+----------------------------------0 F 3 * a + a $ reduce cu T --> F (4). goto[6. Un element poate sa fie reprezentat de o pereche de numere.F]=3 ---------------+------------+----------------------------------0 E 1 + 6 F 3 $ reduce cu T --> F (3).T]=9 ---------------+------------+----------------------------------0 E 1 + 6 T 9 $ reduce cu E --> E + T (0) ---------------+------------+----------------------------------0 E 1 $ succes ---------------------------------------------------------------Problema cea mai importanta este desigur modul in care se construiesc tabelele de analiza. Astfel din productia A --> XYZ rezulta patru elemente : [A--> . Ideea de baza este construirea unui automat finit .T]=2 ---------------+------------+----------------------------------0 T 2 * a + a $ deplaseaza ---------------+------------+----------------------------------0 T 2 * 7 a + a $ deplaseaza ---------------+------------+----------------------------------0 T 2 * 7 a 5 + a $ reduce cu F --> a (6). Dar o astfel de recunoastere poate sa fie realizata de catre un automat finit.5.

elemente care formeaza nucleul.T. doua functii : inchidere si goto si o procedura numita elemente.(E). 2. T --> .determinist care sa stie sa recunoasca elemente LR. T --> . Corespunzator daca B --> t este o productie. urmeaza sa gasim la intrare un sir derivat din BB. E --> .t]} = pina C = C' rezultat C = Daca A --> a . F --> . De exemplu pentru gramatica modificata a expresiilor aritmetice : E' E T F --> --> --> --> E E + T T T * F F (E) a pornind de la setul I = {[E' --> . Gruparea acestor elemente se face pe baza unui algoritm de constructie a subseturilor de tipul celor utilizate pentru construirea automatului finit determinist echivalent unui automat finit nedeterminist dat.a In general pentru o multime T de elemente se poate face impartirea acestora in doua clase : 1. atunci in sirul de intrare ne asteptam sa gasim un sir derivat din t. atunci inchidere(I) este o multime de elemente construite din I utilizind urmatoarea functie : functia inchidere(I) este C = I repeta C' = C pentru fiecare A --> a . Gramatica G' se obtine din G prin utilizarea unui alt simbol de start al gramaticii S' si a unei productii S' --> S care permite recunoasterea starii de acceptare prin utilizarea in reducere a acestei productii.S). pe prima pozitie a partii dreapta. din care se pot genera alte elemente. pe prima pozitie a partii dreapta (cu exceptia elementului S' -->.E]} se obtine inchidere(I) : E' --> .E + T.T * F.F F --> . E --> .E. Pentru aceasta constructie se utilizeaza o gramatica modificata G'. O colectie a multimilor de elemente LR(0) numita multime canonica de elemente LR(0) reprezinta punctul de plecare pentru constructia tabelelor de analiza.S si toate celelalte elemente din I care nu au . Daca I este o multime de elemente pentru o gramatica G. Se grupeaza elementele in multimi care reprezinta starile unui automat finit nedeterminist care recunoaste prefixe viabile. In aceasta clasa intra elementul S' --> . elemente care nu fac parte din nucleu si care au . B B face parte din inchidere(I) la un moment dat in procesul de analiza. B B E C executa /* B E N */ fie B --> t o productie pentru B C = C U { [B --> . .

] nu este un astfel de element in schimb se observa ca elementul [E --> E.S]})} repeta C' = C pentru fiecare multime I E C fiecare X E N U T executa daca goto(I. Se calculeaza goto(I.X) unde I este o multime de elemente (deci o stare a automatului finit utilizat in recunoasterea prefixelor viabile) si X E N U T se defineste ca fiind inchiderea tuturor elementelor [A --> a X. [F --> .Se observa ca orice element care nu face parte din nucleu poate sa fie generat prin operatia de inchidere dintr-un element din nucleu.F]. B] astfel incit [A --> a .XB] E I} Functia goto(I.X) este fie J = {[A --> aX. [T --> . + T] satisface conditia.X)} = = pina cind C = C' = Pentru gramatica expresiilor aritmetice sa consideram din nou diagrama de tranzitii pentru capetele care pot sa apara in stiva: +----+ E +----+ + +----+ T +----+ * ----> I1 -----> -----> I9 -----> I7 +----+ +----+ F I6 -----> I3 ( -----> I4 a -----> I5 +----+ . De exemplu daca I = {[E' --> E. T] si se face inchiderea multimii care contine acest element.X) E/ C atunci C = C U {goto (I.(E)]. daca I este o multime de elemente utilizate pentru prefixe de forma t. Se poate construi multimea canonica a multimilor de elemente LR(0) pentru o gramatica G' modificata in modul urmator : procedura elemente C = {inchidere ({[S' --> .+) examinind multimea I pentru elemente avind simbolul + dupa punct. X B] este in I. Corespunzator este suficienta memorarea numai a elementelor din nucleu (celelalte elemente putind sa fie generate prin operatia de inchidere).B] rezultat inchidere(J) = [A --> a.X) =/ O/ & goto(I.+) va contine {[E --> E + . + T]} atunci goto(I. functia goto(I. [E --> E.X) este multimea de elemente utilizate pentru prefixul tX.T * F]. Se va muta punctul peste simbolul + si se va obtine elementul [E --> E +. [F --> . atunci goto(I.T].a]}. Intuitiv.]. De exemplu elementul [E' --> E. [T --> .

Acest arc va fi etichetat cu ?. E.t] daca B --> t este o productie.F .E) . + T. Daca A --> B1 . I1 : E' E I2 : E T I3 : T I4 : F E E T T F F --> --> --> --> --> --> --> --> --> --> --> --> E.) E.I2 ----> I5 \ +----+ \ F +----+ \.(E) .a I5 : F T I6 : E T F T F F T I7 : T F F F I8 : F E --> --> --> --> --> --> --> --> --> --> --> a. se observa ca va exista o tranzitie de la nodul corespunzator elementului [A --> a.E .(E) . B2 este valid pentru a B1 si B2 =/ ? atunci nu s-a gasit inca un capat deci urmatoarea operatie trebuie sa fie o deplasare. (. E + . Exista o tranzitie de la nodul corespunzator elementului [A --> a.a E + T.( \ / ( +----+ E +----+ ) +-----+ ----> I4 -----> -----> I11 +----+ +-----+ \\ T I8 + a \\ -----> I6 V \\ +----+ a +----+ \\. B. + T Spunem ca elementul [A --> B1 .F . * F. F . T.T * . Daca B2 = ? atunci se poate aplica pentru reducere productia A --> B1. In acest mod functia goto(I. Rezulta urmatoarea colectie canonica pentru G : I0 : E' E E T T F F I9 : E T I10: T I11: F --> --> --> --> --> --> --> --> --> --> --> . B2] este valid pentru un prefix viabil a B1 daca exista o derivare dreapta S ==*> a A w ==*> a B1 B2 w. * F T * F.T +----+ * +----+ F +-----+ ----> I2 -----> -----> I10 +----+ +-----+ I7 ( ------> I4 I0 a ------> I5 +----+ F +----+ ----> I3 +----+ .T * F .a (E. Aceasta tranzitie (arc) va fi etichetata cu X.a T *. Problema este ca pentru .E + .T .(E) .X B] la nodul corespunzator elementului A -> a X .(E) .F . B B] la nodul corespunzator elementului [B --> . Daca consideram automatul finit nedeterminist pentru care starile sint elemente.X) va indica tranzitia din starea I pe baza simbolului X in automatul finit determinist. Operatia de inchidere este de fapt operatia de construire a automatului finit determinist echivalent unui automat nedeterminist dat. (E).T . T.T * F . In general un element este valid pentru mai multe prefixe viabile.I3 Daca fiecare stare cu exceptia starii I0 este o stare finala se observa ca aceasta diagrama poate reprezenta automatul finit nedeterminist care accepta prefixe viabile.E + T .T .

(E) iar pentru ultima F --> . [F --> . Dindu-se o gramatica G se utilizeaza gramatica G' (obtinuta prin inlocuirea simbolului de start al gramaticii S cu un simbol S' si adaugarea productiei S' --> S) pentru a construi C. . a B] E Ii si goto(Ii.. F]. Starea I7 contine elementele : [T --> T *. F. Sa consideram de exemplu urmatoarele derivari dreapta : E' ==> ==> ==> ==> ==> E E E E E + + + + T T * F T * a T * F * a E' ==> ==> ==> ==> E E' ==> E E + T ==> E + T E + T * F ==> E + T * F E + T * (E) ==> E + T * a Pentru prima derivare se va folosi elementul T --> T *.] E Ii & A =/ S' atunci pentru fiecare a E FOLLOW(A) executa actiune[i. In} multimea canonica a multimilor de elemente LR(0) pentru G'.. De fapt aceste elemente valide contin toate informatiile necesare referitoare la continutul stivei. 2.acelasi prefix se pot gasi mai multe elemente valide.(E)]. pentru a doua F --> . Algoritmul care va fi prezentat in continuare nu produce in mod necesar tabele cu intrari continind un singur termen pentru orice limbaj de programare dar poate sa fie utilizat cu succes pentru majoritatea constructiilor din limbajelor de programare. Se poate demonstra ca multimea elementelor valide pentru un prefix viabil t este multimea elementelor care sint parcurse pornind din starea initiala de a lungul unei cai etichetate cu t in automatul finit determinist construit din multimea canonica de multimi de elemente cu tranzitii date de functia goto. se construieste C = {I0. multimea canonica de multimi de elemente pentru G'.a] = "reduce A --> a" = = c) daca [S' --> S.. Sa consideram din nou gramatica expresiilor aritmetice.$] = "succes" = . [F -->. deci in general poate sa apara un conflict care eventual poate sa fie solutionat pe baza urmatorului simbol de la intrare (LR(1)). Intrarile in tabela actiune pentru starea i se obtin in modul urmator : a) daca [A --> a .a] = "deplaseaza j" /* a E T */ = b) daca [A --> a. starea i este corespunzatoare multimii Ii.a]. Automatul se va gasi in starea I7 dupa parcurgerea acestui prefix. I1. Se observa ca E + T * este un prefix viabil. Algoritmul care produce tabelele de actiune si goto utilizeaza urmatorul algoritm : Intrare O gramatica G' Iesire Tabele de analiza pentru G' Algoritmul parcurge urmatoarele etape : 1.a) = Ij atunci actiune[i. Construirea tabelelor de analiza SLR se face pornind de la automatul finit care accepta prefixe viabile.a pentru prefixul viabil E + T *.] E Ii atunci actiune [i.

T --> . E --> E. Pentru T --> T.A) = Ij /* tranzitia din starea Ii in starea Ij se face pentru simbolul A */ atunci goto[i. Tabelele de analiza construite conform regulilor anterioare formeaza tabela SLR(1) pentru G..+] = actiune[2. Sa consideram intii multimea I0 : E' --> .T.*R L --> . E --> .L L --> .(E) se obtine actiune[0. + T se obtine actiune[1.L I1: S' --> S. Pentru I1: E' --> E.. T --> T. Reciproca nu este adevarata. rezulta actiune[2.*] = "deplasare 7".(] = "deplasare 4".a se obtine actiune[0.R L --> . I3: S --> R.a I5: L --> a. = R R --> L.L L --> . F --> .a I7: L --> *R. I6: S --> L = . Intrarile in tabela goto pentru starea i se obtin in modul urmator : daca goto (Ii. FOLLOW(E) = {$. toate intrarile necompletate prin regulile 2 si 3 sint marcate cu eroare 5.)] = "reduce E -> T". Continund se obtine tabela utilizata pentru a ilustra functionarea algoritmului de analiza LR.E + T. I8: R --> L.$] = "succes". 3. Un analizor LR care lucreaza cu tabele SLR(1) este un analizor SLR(1). * F se obtine actiune[2.R R --> . * F. . I4: L --> *. I2: S --> L. actiune[1. I2 este format din E --> T.A] = j = 4.)}.* R L --> .a R --> . Starea initiala a analizorului este cea care corespunde multimii de elemente care contine elementul [S' --> .F.+] = "deplasare 6". T --> .E.a] = "deplasare 5".$] = actiune[2.T * F.*R L --> .(E). E --> .Daca in construirea tabelei actiune apar conflicte gramatica nu este SLR(1) si trebuie sa fie utilizata o alta metoda.S S --> . Sa construim de exemplu analizorul SLR(1) pentru gramatica expresiilor aritmetice. Din elementul F --> .L = R S --> . Orice gramatica SLR este neambigua.S]. Celelalte elemente nu produc actiuni. din F --> .R R --> .+. Sa consideram de exemplu gramatica : (1) (2) (3) (4) (5) S S L L R --> --> --> --> --> L = R R *R a L Multimea canonica de multimi de elemente este : I0 : S' --> . F --> . I9: S --> L = R.a.

=] = "reduce R --> L.=] = "deplasare 6".2.]. . Se observa ca desi gramatica nu este ambigua a aparut un conflict deoarece metoda folosita nu este suficient de puternica neputind sa memoreze suficienta informatie pe baza careia pentru terminalul = sa se stabileasca ce actiune trebuie sa se execute pentru un sir care poate sa fie redus la L. Analiza canonica LR Prezentam in continuare metoda cea mai generala pentru construire a tabelelor LR(1) pentru o gramatica data. prefixul Ba din stiva este astfel incit B A nu poate sa fie urmat de a intr-o derivare dreapta si deci nu se poate face reducerea A --> a. Exista situatii. cu = pe banda de intrare. deci = E FOLLOW(R) si deci actiune[2.2. FOLLOW(R) C_ FOLLOW(L) C_ FOLLOW(R) deci FOLLOW(R) = FOLLOW(L).. Pentru metoda considerata anterior in starea i se face reducere cu productia A --> a daca multimea Ii contine elementul [A --> a.Diagramele de tranzitie pentru prefixele viabile sint : +------+ +----+ S +----+ ----> I1 +----+ +------+ L +----+ = +----+ a ----> I2 -----> ------> I5 +----+ R +----+ ------> I9 I6 +----+ L +----+ ------> I8 * +----+ ------> I4 +----+ +------+ R +----+ I0 ----> I3 +----+ +------+ * ___ \ / * +----+ ----> R +----+ ------> I7 I4 +----+ L ------> I2 +----+ V a a +----+ ----> I5 +----+ +----+ Sa consideram elementul I2 pentru care se obtine actiune[2. in care daca i apare in virful stivei. 3. s-a aratat ca = E FOLLOW(R) si deci se pune problema aplicarii reducerii R --> L (virful stivei contine L)... Dar nu exista nici o derivare dreapta care sa inceapa cu R = .5. = E FOLLOW(L). Reluind ultimul exemplu pentru starea I2 si elementul [R --> L.] si a E FOLLOW(A) urmeaza in sirul de intrare.

b] E/ I . Se observa ca utilizarea conditiei a E FOLLOW(A) este prea slaba in cazul general. Sa consideram un element de forma [A --> a . B. a] cu A --> aB o productie si a E T U {$}.t. fie w = ? si a = $. Forma generala a unui element devine [A --> a . a] E I. Pentru un element de forma [A --> a . fiecare b E FIRST(Ba) executa daca [B --> .a]. b] este valid pentru t. B = B in definitia anterioara. Pentru aceasta derivare elementul [B --> a .a] este valid pentru un prefix viabil t daca exista o derivare : S ==*> sAw ==> saBw. B. $] este valid pentru prefixul Baa..a] este valid pentru prefixul viabil aaa considerind s = aa. B B. a] si B =/ ? atunci a nu ofera o informatie suplimentara. Elementul [B --> a. y E T*. B.r. B. vom avea derivarile S ==*> tBby ==> trby. Pentru elementele [A --> a. Metoda de construire a multimii de elemente LR(1) valide este aceasi cu cea pentru construirea multimii canonice de multimi de elemente LR(0) cu modificari adecvate ale procedurii inchidere si goto. Fie derivarea S ==*> aaBab => aaaBab. Un astfel de obiect se numeste element LR(1). fiecare productie B --> t. De asemenea sa consideram si derivarea S =+> BaB => BaaB. Deci. fie a este primul simbol din w. Algoritmul utilizeaza urmatoarele proceduri auxiliare : functie inchidere(I) este repeta I' = I pentru fiecare element [A --> a . Se poate observa ca b este primul simbol terminal derivat din B. 1 se refera la numarul de simboli terminali luati in considerare pentru a se hotari daca sa se efectueze o reducere. b E . a E T. daca exista o derivare dreapta S ==* sAax ==> saBBax cu t = s a. B E (N U T)*. Alta solutie consta din adaugarea unei informatii pentru fiecare element obtinindu-se elementele LR(1). B E N.Deci nu trebuie aplicata reducerea. t = sa si 2. a]. A . a. [B -->. Altfel spus b E FIRST(Bax) (FIRST(Bax) = FIRST(Ba). sau daca B ==*> ?. Sa presupunem ca B a x ==*> by. a]. B a x ==*> by si deci b = a.B. Rezulta urmatorul algoritm de construire a elementelor LR(1) : Intrare O gramatica G' Iesire multimile de elemente LR(1) valide pentru unul sau mai multe prefixe din G'. Informatia suplimentara este incorporata in stare prin redefinirea elementelor astfel incit fiecare element sa contina ca a doua componenta un simbol terminal. O solutie este transformarea gramaticii astfel incit pentru automatul care rezulta sa fie bine precizat ce simbol de intrare poate sa urmeze unui capat pentru care exista posibilitatea unei reduceri. Acest element este valid pentru un prefix t.. a =/ ?). Se consideram de exemplu gramatica S --> BB. a = a. Atunci pentru orice productie B --> r. A = B w = ab. a E FOLLOW(A) dar nu toate elementele din FOLLOW(A) apar in elementele LR(1) de forma [A --> a. a] se va face o reducere utilizind productia A --> a daca si numai daca urmatorul simbol de intrare este a.. unde 1. Daca un element este de forma [A --> a . B --> aB b. Se spune ca elementul LR(1) [A --> a . B B.

B = ?.S.BB. [C --> . Rezulta adaugarea elementului [S --> .atunci I = I U {[B --> .a] E I} rezultat inchidere(J) = procedura elemente(G') C = {inchidere ( { [S' --> . FIRST(C$) = FIRST(C) = {c. de data aceasta A = S. Se vor adauga deci elementele [C -->. B = C. d]. Deoarece C ==*/> ?.d]. b] pentru fiecare productie de forma B --> t si fiecare b E FIRST(Ba).d.d.t. $]}. pe post de b va fi $.$] componentele elementului generic [A --> a.cC.XB.$ . a = $. fiecare X E N U T executa daca goto(I. Singura productie care se potriveste este S --> CC. Sa identificam in elementul [S' --> .X)} = = pina C' = C Sa consideram de exemplu gramatica S' --> S.$ .$] cu [A --> a. Daca X = S se va calcula inchiderea elementului [S' --> S. a = $.S.BB. Din modul de actiune al functiei inchidere se observa ca se adauga termeni de forma [B --> . Sa consideram acum productiile care au C in partea stinga pentru care trebuiea sa se adauge elementele [C -->.B.a]. S --> CC. pentru ca Ba =$.S.t. B = C.X) pentru diferitele valori posibile pentru X.d.cC. B = S. C.cC. $].S. [C --> .$ . c/d Sa calculam goto(I0.$ Daca X = C vom calcula inchiderea pentru S --> C .b]} = = pina I = I' rezultat I = functie goto(I. d}.c/d . $] la inchidere ([{[S' --> .a]. Comparind din nou elementul [S -->..CC.CC. [C -->.$]})}.CC.b] pentru b E FIRST(C$). $ I2 : S --> C. c].c].. Rezulta A = S'. Se observa ca nu mai exista elemente cu un neterminal la dreapta punctului deci s-a obtinut : I0 : S' S C C --> --> --> --> .a] [A --> a.S. C --> cC d. a = ?.C.X) este fie J = {[A --> aX.$]}. Se incepe cu calculul multimii inchidere({[S' -->. Rezulta : I1 : S' --> S.t. a = ?.X) E/ C atunci C = C U {goto(I. repeta C' = C pentru fiecare I E C.X) =/ O/ si goto(I.

c/d C --> . c/d I9: C --> cC. I2. I4 se obtine : I5: S --> I6: C --> C --> C --> CC. c/d C --> . se calculeaza inchiderea pentru {[C --> c.$ . rezulta urmatorul algoritm de construire a tabelelor de analiza pentru G'.cC.$ C --> . I3. Rezulta urmatorul graf al automatului : +----+ 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 obtinute pentru automatul finit descriere ce s-a construit utilizind functiile goto si inchidere.. I3 : C --> c. c/d]}.$ I8: C --> cC..$ .cC.C.d.C..$ c.d.d.cC.$ Daca X = c.C. c/d In aces mod s-a terminat calculul pentru inchidere continuind pentru I1..c/d Pentru X = d I4 : C --> d. Intrare o gramatica G' Iesire Tabelele de analiza actiune si goto pentru G' Algoritmul parcurge urmatoarele etape : . $ I7: C --> d.$ (I0).C --> ..

A =/ S' atunci actiune[i.$]. dar tabela de .a) = Ij /* a E T */ atunci actiune[i. se construieste C = {I0.$] = "succes" = = Daca din cele regulile anterioare rezulta un conflict atunci inseamna ca gramatica nu este LR(1) si executia algoritmului se opreste. pentru fiecare Ii E C & fiecare A E N executa daca goto(Ii.a B. .a] = "reduce A --> a" = daca [S' --> S.a] = "deplaseaza j" = daca [A --> a. In} multimea de multimi canonice de elemente LR(1) pentru G'. Aplicind acest algoritm pentru gramatica care are productiile : (1) S --> CC (2) C --> cC (3) C --> d se obtin 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 gramatica SLR(1) este evident o gramatica LR(0).A) = Ij atunci goto [i... pentru fiecare stare i reprezentata prin multimea Ii executa daca [A --> a. a] E Ii.. $] E Ii atunci actiune[i.S.1. Toate intrarile necompletate corespund unor situatii de eroare 5. 2.. b] E Ii & goto(Ii. Starea initiala a analizorului se obtine din multimea care contine elementul [S' --> .A] = j = = 4. 3.

Valorile din tabela goto si actiune vor reflecta aceste reuniuni prin modificari corespunzatoare. Gramatica pe care am considerat-o genereaza siruri de forma c*dc*d.analiza LR(1) pentru aceasi gramatica are mai multe stari decit tabela de analiza SLR. I7 : C --> d. c/d . Pentru exemplul considerat multimile I4 si I7 au ca miez multimea {C --> d. Pentru un limbaj cum este PASCAL-ul tabelele de analiza LALR si SLR au sute de intrari in timp ce tabelele canonice au citeva mii..X) depinde numai de miezul multimii I. Trimiterile in I4 pentru d din I0. Deci exista situatii in care in loc de semnalarea unei erori se va face reducerea C-->d. Corespunzator se poate face reuniunea multimilor goto pentru doua multimi care au acelasi miez. Reducerea este corecta deoarece c sau d pot sa inceapa sirul c*d care trebuie sa urmeze. Sa reluam din nou gramatica G' : S' --> S.. Adica tabela goto va reflecta noile multimi intre care se fac tranzitii iar tabela actiune va avea inlocuite o serie de intrari de eroare cu intrari de reducere. Se observa ca in acest caz dintre elementele pentru care s-a facut reuniunea exista si elementele [A --> a. a t. de asemenea multimile I3 si I6 au ca miez multimea {C --> c. C --> cC d si sa analizam multimile canonice I4 si I7 : I4 : C --> d. De exemplu pentru sirurile ccd sau cdcdc. Tabelele construite utilizind aceasta metoda sint mai mici (exista mai putine stari) decit tabelele canonice LR si de asemenea majoritatea constructiilor din limbajele de programare pot sa fie exprimate convenabil utilizind gramatici LALR.C.d}. In general un miez este o multime de elemente LR(0). a] care indica o reducere cu A --> a si exista un alt element [B --> B. dupa care se va face o reducere C --> d daca se intilneste un c sau un d. Sa presupunem ca s-a construit o gramatica LR(1) fara conflicte. I2. Dupa d se intra in starea 7 dupa care trebuie sa urmeze $ sau sirul de intrare nu este corect. c/d/$].5. b] care indica o deplasare. Daca inlocuim toate multimile cu acelasi miez cu reuniunea lor s-ar putea dar este putin probabil sa apara conflicte. Sa consideram ca reunim cele doua stari sub forma unui element [C --> d. Analiza sintactica LALR Numele LALR porneste de la termenul lookahead .. pentru I7 se utilizeaza $. Deci analizorul va deplasa initial sirul de c si va intra in starea I4 dupa intilnirea simbolului d.cC. a] si [B --> B. Daca insa apare $ inseamna ca sirul s-a terminat prea devreme (de exemplu este de forma ccd). Inseamna ca aceste elemente prezinta acelasi conflict deplaseaza / reduce pentru terminalul a si gramatica nu ar mai fi LR(1) asa cum s-a . Sa presupunem ca exista un conflict datorita unui simbol a E T deoarece exista un element [A --> a. Actiunea din I47 va fi de reducere pentru orice intrare. In general se cauta multimi de elemente LR(1) avind acelasi miez (aceeasi multime a primelor componente pentru elemente) si se face o reuniunea acestor multimi de elemente. S --> CC. b] pentru un anumit b. O gramatica LR(1) poate produce mai multe multimi cu acelasi miez. C --> .3. I3 si I6 vor fi spre I47.}. Eroarea se va depista inainte de a se mai considera un alt caracter de intrare. $ Pentru I4 simbolii terminali utilizati sint c si d..2.at. 3.LR. C -->.. Se observa ca miezul multimii goto(I.

. Daca se construieste reuniunea acestor multimi se obtine multimea {[A --> c. Sa consideram de exemplu gramatica : S' --> S. e]} ale carui elemente sint valide pentru prefixul ac si multimea {[A -->c. B --> c... S --> aAd bBd aBe bAe. ace. . bce. Fie K reuniunea tuturor multimilor care au acelasi miez cu goto(I1.. .d]. se construieste C = {I0. . Jm} multimea de multimi de elemente LR(1) rezultata. C --> cC d pentru care s-a obtinut diagrama de tranzitii : +------+ +-----+ S +----+ -----> I1 +----+ +------+ +------+ C +----+ C +----+ -----> I2 ------> I5 +----+ +------+ c __ \/ +------+ c +----+ C +----+ ------> I6 -----> I9 +----+ +----+ .. Aceasta gramatica genereaza sirurile : acd. Se pot utiliza doua metode pentru construirea tabelelor LALR.. 4.. De obicei transformari asupra gramaticii rezolva problema.. deoarece multimile I1. Tabela goto se construieste in modul urmator. Pentru fiecare miez se obtin toate multimiile avind miezul respectiv si se inlocuiesc multimile respective cu reuniunea acestora. Dar poate sa apara un conflict reduce / reduce. Construind multimea elementelor LR(1) se va obtine multimea { [A --> c. bcd...presupus.J1.X).X) atunci goto(J. Deci un conflict deplaseaza / reduce nu poate sa apara prin reuniunea multimilor de elemente cu acelasi miez daca un astfel de conflict nu a aparut intr-una din starile initiale deoarece deplasarile depind numai de miez.X)... Ik au acelasi miez.. A --> c.. d/e] pentru care se observa ca exista un conflict reduce/reduce. [B -->c.I1. Prima metoda porneste de la tabelele LR(1) din acest motiv este foarte consumatoare de memorie si timp. d/e]. nu si de simbolii care urmeaza pe banda de intrare.I2. Daca apare un conflict algoritmul nu poate continua si gramatica nu este LALR(1)..X) = K. B --> c... Fie C' = {J0. Pentru o stare i actiunea corespunzatoare rezulta din Ji ca si in cazul algoritmului pentru construirea tabelelor LR(1). Daca J este o reuniune de forma I1 U I2 U . Sa consideram din nou gramatica S' --> S. goto(Ik.d]} ale carui elemente sint valide pentru prefixul bc. Acest conflict semnifica faptul ca gramatica nu este LALR(1). e]. S --> CC.X) au acelasi miez.. [B --> c.. Intrare O gramatica G' Iesire Tabelele LALR de analiza actiune si goto pentru G' Algoritmul parcurge urmatoarele etape : 1.In} multimea canonica a multimiilor de elemente LR(1) 2. U Ik atunci starile goto(I1.. goto(I2. 3.

c/d/$ C --> .d. I36 : C --> c. Se vor reuni multimile I3 si I6 in I36.C).d V +------+ I0 d +----+ ------> I7 +----+ +----+ +------+ c __ \/ +------+ c +----+ C +----+ -----> I3 -----> I8 +----+ +----+ d V +------+ +------+ d +----+ -----> I4 +----+ +-----+ +------+ +------+ Asa cum s-a mai aratat exista 3 perechi de multimi care au acelasi miez.. c/d/$ si multimile I8 si I9 in I89 : I89 : C --> cC. In tabelele stare . c/d/$ multimile I4 si I7 in I47 : I47 : C --> d.cC.. c/d/$ C --> . c/d/$ Se obtine tabela de analiza : actiune goto c d $ S C --------+-----------+-----0 s36 s47 1 2 --------+-----------+-----1 acc --------+-----------+-----2 s36 s47 5 --------+-----------+-----36 s36 s47 89 --------+-----------+-----47 r3 r3 r3 --------+-----------+-----5 r1 --------+-----------+-----89 r2 r2 r2 ---------------------------+ Sa vedem de exemplu cum s-a calculat goto(I36.C.

Daca [B --> t . Pentru un sir de forma c*dc*d cele doua analizoare LR(1) si LALR(1) realizeaza aceleasi miscari.C) = I89. L --> *R a. Prima observatie este ca orice multime de elemente LR(1) poate sa fie reprezentata prin nucleul sau. X s. Asa cum am aratat algoritmul anterior este foarte consumator in termeni de timp si memorie ocupata. b] in nucleul multimii I si C ==*> A u pentru un sir u. atunci calculul multimii de elemente pornind de la nucleu este doar cu putin mai putin eficient decit calculul care utilizeaza inchiderea nucleului. I6 : S --> L =. Multimea neterminalelor A astfel incit C ==*> A u poate sa fie calculata pentru fiecare neterminal C. I8 face parte din I89 deci goto(I36. Actiunile de deplasare pentru I pot sa fie determinate din nucleul multimii I in modul urmator. Daca se aplica la intrare un sir incorect analizorul LALR poate sa continue sa efectueze miscari si dupa miscarea la care analizorul LR(1) a identificat o eroare. Daca pentru fiecare pereche C si A calculam de la inceput daca exista o derivare C ==*> A u pentru un sir u.C) = I89. Urmeaza o noua reducere cu C --> cC si se obtine in stiva 0 C 2 pentru care se va recunoaste situatia de eroare. s. Se executa o deplasare pe baza intrarii a daca exista in nucleu un element [B --> t . b] astfel incit C ==*> A u pentru un sir u si a E FIRST(u s b).S din multimea initiala de elemente (I0).LR(1).C) = I9 deci goto(I36. C s. etc.X). b] este in nucleul multimii I. Sa consideram de exemplu gramatica : S' --> S.c) = I6 deci in noua tabela goto(I2. atunci [B --> t X . Se observa ca analizorul LR(1) va ajunge in configuratia cu 0 c 3 c 3 d 4 in stiva cind analizorul LR(1) ar detecta eroare pentru ca nu este definita o actiune pentru starea I4 si intrarea $. A doua observatie este ca se pot calcula actiunile de analiza pentru o multime de elemente I utilizind numai elementele din nucleu. Reducerile cu A --> ? se vor face pentru simbolul de intrare a daca si numai daca in nucleu exista un element [B --> t . I5 : L --> a. Apoi. R R. se calculeaza nucleele multimiilor goto pentru I0.S I1 : S' --> S. Fie de exemplu secventa de intrare ccd$. S --> L = R Se obtin nucleele : I0 : S' --> .C) = I8.a] este de asemenea in nucleul multimii goto(I. C s. Elementul [A --> X.c) = I36. C s. Pentru multimea I se pot construi tranzitiile goto pe baza nucleului. Orice element pentru care trebuie sa se faca o reducere A --> a va fi in nucleu cu exceptia cazurilor in care a = ?.X) daca exista un element [B --> t . R --> L . goto(I3. Pentru a calcula multimiile de elemente LALR(1) pentru o garmatica G' se porneste cu nucleul S' --> . B. b] cu C ==*> ax si ultimul pas in derivare nu utilizeaza o ? productie. Se continua pina se obtin nucleele pentru toate multimiile de elemente LR(0). b] este in nucleul pentru goto(I. Pentru I2 in tabela LR(1) goto(I2. Multimea simbolilor a poate sa fie calculata pentru orice C. De asemenea goto(I6. Acest algoritm se poate insa modifica pentru a evita construirea completa a multimii LR(1) de elemente in procesul crearii tabelelor de analiza LALR(1). In analizorul LALR dupa ce se ajunge in starea cu continutul stivei 0 c 36 c 36 d 47 se va efectua o reducere cu C --> d si stiva va contine 0 c 36 c 36 C 89 apoi 0 c 36 C 89 (s-a efectuat o reducere cu C --> cC).

C s la A --> X. B. a] E goto(I.X). B. s din I la elementul A --> a X. In continuare se face extinderea nucleului atasind fiecarui element LALR(0) cel de-al doilea element. Vom spune in acest caz ca a doua componenta s-a propagat de la B --> t . I8 : R --> L. B in goto(I. = R --> L.B. X B. Daca a E FIRST(u s) atunci derivarea C ==*> A u indica faptul ca [A --> X. pentru fiecare element B --> t . C s. I9 : S --> L = R.a] trebuie sa fie in goto(I. --> R. X B. Sa presupunem ca C ==*> A u pentru un sir u si A --> X B este o productie.b] E goto(I.X) este : Intrare Nucleul K al multimilor de elemente LR(0) si un simbol X Iesire Simbolii generati spontan de elementele din I pentru elementele de nucleu din goto(I. 2. In acest caz.X) sa consideram un element LR(0) [B --> t. a] E J' si a =/ # atunci se genereaza a in mod spontan si [A -->aX. s E K executa J' = inchidere ({B --> t .S in multimea initiala de elemente.I2 : S R I3 : S I4 : L --> L. s. #] E J' atunci se propaga componentele doi pentru elementele de forma B --> t .X). In algoritm se utilizeza un simbol fictiv # pentru a detecta situatiile in care se produce propagarea. Algoritmul de determinare a celei de a doua componente pentru elementele goto(I. B. --> *. B este in goto(I.X). B.X). Se aplica algoritmul anterior pentru fiecare nucleu de multime de elemente LR(0) si fiecare simbol X pentru a determina care . C s] E I. #]}) daca [A --> a. In acest caz A --> X. Prin constructie $ este generat in mod spontan pentru elementul S' --> .X) = = Algoritmul prin care se competeaza toate componentele doi asociate cu elementele multimiilor LALR(0) de elemente este : Intrare O gramatica G' Iesire Nucleele multimii LALR(1) de multimi de elemente pentru G' Algoritmul parcurge urmatoarele etape : 1.B.a] E goto(I.X) si elemenetele din nucleul multimii I pentru care se produce propagarea celei de a doua componente.R I7 : L --> *R. Se construiesc nucleele pentru multimiile LR(0) de elemente din G. Pentru a vedea cum se propaga un simbol terminal care apare ca a doua componenta pentru un element LR(1) de la multimea I la multimea goto(I.B. Dar mai exista o sursa de componente pentru A --> X . valoarea simbolului b este nesemnificativa si spunem ca a este generat in mod spontan pentru elementul A --> X . b] E I se pune problema care sint simbolii a E T U {$} astfel incit [A --> X. Daca se calculeaza elementele LR(1) si [B --> t .X) = daca [A --> a . Daca u s ==*> ? atunci [A --> X.

se cauta elementele in care acest element isi propaga a doua componenta. R --> . multime element Init etapa 1 etapa 2 etapa 3 --------+-------------+------+---------+---------+--------I0 S' --> .R I5 : L --> a. I9 : S --> L = R. L --> *R a.=] pentru I4 si elementul [L --> .. I3 : S --> R.=] produce elementul [L --> *. Astfel elementul [L --> . I8 : R --> L. R I4 : L --> *. Sa aplicam algoritmul de calcul al componentelor doi pentru elementele din multimea goto(I. Initial pentru fiecare element sint asociate numai acele componente care au aparut spontan in etapa 2. S --> . I8 : R --> L. Se observa ca de la S' --> . = R I2 : R --> L.R ------------------+--------------------------I4 : L --> *. Se observa ca pentru I0 starile urmatoare pot sa fie I1. =] pentru I5.S $ $ $ $ --------+-------------+------+---------+---------+--------- . Se parcurg in mod repetat elementele din nucleele tuturor multimilor. I3.S se propaga $ pentru fiecare componenta doi din nucleele din I1. # Doua elemente din aceasta multime produc in mod spontan componente noi. #/=. I5. = R I6 : S --> L = . I7 : L --> *R.R.X). Propagarea componentelor se face in modul urmator : de la la ------------------+--------------------------I0 : S' --> . L --> .R.*R. ..=] produce elementul [L --> a. ------------------+--------------------------I6 : S --> L =. I2 : S --> L. I2. Inchidere ({[S' --> .#]. S --> L = R R. # . Sa construim de exemplu nucleele pentru elementele LALR(1) pentru gramatica S' --> S. I4 : L --> *. Pentru I0 calculam numai inchiderea pentru elementul nucleului [S' --> .S. R --> L pentru care s-au calculat multimiile LR(0). # . 4.sint componentele generate spontan si care sint componentele propagate pentru multimea goto(I. Se repeta operatia pina nu se mai pot face noi propagari. Se initializeaza o tabela care indica pentru fiecare element din nucleu din fiecare multime de elemente.S I1 : S' --> S.L = R.R I5 : L --> a. ------------------+--------------------------I2 : S --> L.S. Cind se cerceteaza un element i. L --> . I5. #]}) este : S' --> .S.R I4 : L --> *. 3.R I5 : L --> a.L.a. # .a. I4. S --> ..X) pentru nucleul multimii I0. Sa consideram si rezultatul etapelor 3 si 4.*R. #/=. componenta a doua asociata..

R = =/$ =/$ =/$ --------+-------------+------+---------+---------+--------I5 L --> a. De exemplu pentru tabela : stare actiune goto c d $ S C -------+---------------+----------0 s3 s4 1 2 -------+---------------+----------1 succes -------+---------------+----------2 s6 s7 5 -------+---------------+----------3 s3 s4 8 -------+---------------+----------- . = R in I2. 3. Din acest motiv modul in care se memoreaza aceste tabele este foarte important. Se observa ca numai apare conflictul deplasare / reducere care aparea pentru metoda SLR.4. $ $ $ --------+-------------+------+---------+---------+--------I4 L -->*.R $ $ --------+-------------+------+---------+---------+--------I7 L --> *R. Compactarea tabelelor LR Dupa cum s-a aratat dimensiunile tabelelor LR pot sa fie semnificative. Se propaga si la I4 si la L --> a. Pentru fiecare se mentine un pointrer catre inceputul liniei respective. din I8.5. = =/$ =/$ =/$ --------+-------------+------+---------+---------+--------I6 S --> L=. In etapa 2 si 3 singura componenta care se propaga este $ peentru succesoare multimilor I2 si I4 in etapa 2 si pentru succesoarele starii I6 pentru etapa I3.=R $ $ $ --------+-------------+------+---------+---------+--------I2 R --> L. in I2 deci nu poate apare nici un conflict legat de actiunea de deplasare bazata pe = generat pe baza elementului S --> L. $ $ $ --------+-------------+------+---------+---------+--------I2 S --> L. $ $ $ --------+-------------+------+---------+---------+--------I3 S -->R. pentru ca numai componenta $ este asociata cu R --> L. pentru etapa 4 nu se mai propaga nimic asa ca executia algoritmului se opreste. Componenta = se propaga de la L --> *.R in I4 la elementele L --> *R. De exemplu.I1 S' --> S. din I7 si R --> L. = =/$ =/$ --------+-------------+------+---------+---------+--------I9 S --> L = R. avind in vedere ca exista de obicei mai multe linii identice in tabela actiunilor se poate construi un vector de actiuni in care sa fie inscrise una dupa alta fiecare linie din tabela de actiuni. = =/$ =/$ --------+-------------+------+---------+---------+--------I8 R --> L. din I5 dar in aceste componente sint continute deja in aceste elemente. Daca exista mai multe linii identice in vector va fi inscrisa numai una dintre ele.2. $ -----------------------------------------------------------+ Coloana Init indica componentele doi pentru fiecare element din nucleu.

----------------------------+ --3 --+ --4 ----------------------------------------------+ . O alta posibilitate este crearea unei liste pentru actiunile fiecarei stari.. Sa consideram de exemplu tabela de actiuni pentru gramatica expresiilor aritmetice : actiune goto si . Fiecare terminal are un cod corespunzator coloanei din tabela de actiuni LR.reprezinta reducerea cu productia j acc . +---------------------------------------------------------------^^ ^ ^ ^ +---+ 0 -+ --1 -.reprezinta succes blanc .-------------+ --2 -. Actiunea care apare in cele mai multe intrari va fi trecuta la sfirsitul listei.actiune). O lista este formata din perechi (terminal.reprezinta deplasare si starea urmatoare i rj .4 r3 r3 -------+---------------+----------5 r1 -------+---------------+----------6 s6 s7 9 -------+---------------+----------7 r3 -------+---------------+----------8 r2 r2 -------+---------------+----------9 r2 -----------------------------------+ Tabela de actiuni va fi reprezentata sub forma : +-----------------------------------------------------------+ s3 s4 succ s6 s7 r3 r3 .reprezinta eroare stare a + * ( ) $ E 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 -------+---+---+---+---+---+---+---+---+--- (1) E --> E + T ....

Avantajul primei gramatici este ca se evita reduceri de forma E --> T. Utilizarea gramaticilor ambigue O gramatica ambigua nu este LR. 4.2. Un element al listei va fi in acest caz de forma (stare_curenta. E . Aceasta modificare poate sa fie facuta pentru ca se va detecta o eroare in pasul urmator. T --> T * F F. T --> F al carui rost este numai sa asigure asociativitatea si relatiile de prioritate. A]).5. Sa consideram de exemplu gramatica ambigua pentru expresii aritmetice simple: E --> E + E E * E (E) a si aceasta gramatica ambigua genereaza acelasi limbaj ca gramatica : E --> E + T T. goto[stare_curenta. Pentru gramatica ambigua se vor obtine urmatoarele elemente LR(0) : I0 : E' --> . Datorita faptului ca anumite constructii ambigue sint utile in descrierea limbajelor de programare trebuie prevazute modificari ale algoritmilor de construire a tabelelor de analiza pentru a trata aceste constructii. Tabela goto poate sa fie reprezentata de o lista de elemente sau ca o lista de perechi de stari pentru fiecare neterminal A. 6.5. F --> (E) a Deosebirea este ca a doua forma ofera o prioritate mai mica operatiei + fata de * si face ca operatorii + si * sa fie asociativi stinga. 3.7 s5 s4 10 -------+---+---+---+---+---+---+---+---+--8 s6 s11 -------+---+---+---+---+---+---+---+---+--9 r1 s7 r1 r1 -------+---+---+---+---+---+---+---+---+--10 r3 r3 r3 r3 -------+---+---+---+---+---+---+---+---+--11 r5 r5 r5 r5 -------------------------------------------+ (2) (3) (4) (5) (6) E T T F F --> --> --> --> --> T T * F F (E) a Se observa ca stariile 0. Pentru o tabela reala (pentru un limbaj de programare tipic) reducerile spatiului de memorie ocupat prin aceste metode pot sa ajunga si la 90% din spatiul necesar.E I5 : E --> E *. si 7 au acelasi continut care poate sa fie reprezentat sub forma urmatoarei liste : terminal a ( orice Pentru starea 2 lista este : terminal * orice actiune s7 r2 actiune s5 s4 eroare Se observa ca s-au inlocuit intrarile de eroare cu reduceri.

pentru E --> E + E. Follow(E) = {+.a I1: E'--> E. * E I2: E E E E E --> --> --> --> --> (.E + E .(E) . I4: E E E E E --> --> --> --> --> E +. (* E Follow(E)) Dar.E E E E --> --> --> --> .E + E . Deci in functie de relatiile intre operatori se poate trata (rezolva) conflictul deplaseaza / reduce care apare.E + E . + E E --> E. aceasta problema poate sa fie rezolvata utilizind informatiile referitoare la prioritatile si proprietatiile de asociativitate pentru operatori.(E) .a I6 : E --> (E.$}.E) .E * E . * E I7 : E --> E + E. Sa presupunem ca utilizam tabelele de actiune SLR. E --> E. Daca vom considera ca operatorul + are prioritate fata de * atunci trebuie sa se realizeze reducerea cu E --> E + E. E --> E. * E I8 : E --> E * E.E + E .a Sa incercam sa construim actiunile pentru starea I7. + E E --> E. * E actiune[7.E * E . E .E * E . I3: E --> a. In acest caz se poate obtine o tabela de analiza LR pentru gramatica ambigua considerata. + E E --> E. analizorul va ajunge in starea 0 E 1 + 4 E 7 cu +a la intrare. * E I9 : E --> (E).*. actiune goto stare a + * ( ) $ E -------+---+---+---+---+---+---+--0 s3 s2 1 -------+---+---+---+---+---+---+--1 s4 s5 acc -------+---+---+---+---+---+---+--- (1) (2) (3) (4) E E E E --> --> --> --> E + E E * E (E) a . + E E --> E. Din nou exista un conflict deplaseaza/ reduce. E --> E. Sa consideram de exemplu sirul de intrare a + a * a pentru care se ajunge in starea 7 dupa parcurgerea sirului a + a. pentru E --> E. Pentru sirul a + a + a.a E E E E --> --> --> --> . De data asta pe baza proprietatilor de asociativitate se poate lua o hotarire referitoare la modul de solutionare a conflictului.E * E .*] = reduce 1. 0 E 1 + 4 E 7 cu * a $ pe banda de intrare.(E) .) E --> E.). Observind ca * are prioritate mai mare decit + inseamna ca va trebui sa se execute deplasarea simbolului * in stiva.(E) . Rezulta : actiune[7.*] = deplaseaza 4.

Pentru aceasta gramatica se obtin elementele LR(0) : I0 : S' S S S I1 : S' --> --> --> --> --> . Cu alte cuvinte termenul e de pe banda de intrare poate face parte numai din partea dreapta a unei productii S --> iSeS deci nici o data nu trebuie sa se faca o reducere pentru acest simbol. Se observa insa ca daca pentru if expresie then instr se face o reducere atunci cind urmeaza else la intrare aceasta reducere este incorecta.a I2 : S --> i.$} se observa ca apare un conflict pentru actiune[4.S . pentru ca follow(S) = {e.2 s3 s2 6 -------+---+---+---+---+---+---+--3 r4 r4 r4 r4 -------+---+---+---+---+---+---+--4 s3 s2 7 -------+---+---+---+---+---+---+--5 s3 s2 8 -------+---+---+---+---+---+---+--6 s4 s5 s9 -------+---+---+---+---+---+---+--7 r1 s5 r1 r1 -------+---+---+---+---+---+---+--8 r2 r2 r2 r2 -------+---+---+---+---+---+---+--9 r3 r3 r3 r3 -------+---+---+---+---+---+---+--10 r3 r3 r3 r3 -------+---+---+---+---+---+---+--11 r5 r5 r5 r5 -----------------------------------+ Sa consideram si gramatica care descrie instructiunile if : instr --> if expresie then instr else instr if expresie then instr alte_instr Aceasta gramatica este ambigua.iSeS . Rezulta rezolvarea conflictului deplaseaza / reduce in favoarea actiunii deplasare. Se obtine urmatoarea tabela de actiuni : actiune goto stare i e a $ E . I3 : S --> a. iSe. Pentru a simplifica notatia sa consideram gramatica transformata : S' --> S S --> iSeS iS a Se observa ca i reprezinta constructia if expresie then.iS .eS iS.e].iSeS . S --> .S S --> .S .iSeS S --> .a Sa consideram multimea de elemente I4.iS I6 : S --> iSeS.iS . I4 : S S I5 : S S S S --> --> --> --> --> --> iS.SeS S --> i.a S.

O posibilitate de eliminare a ambiguitatii consta din proceda ca si in cazul expresiilor aritmetice. Sa consideram de exemplu urmatoarea gramatica care descrie elemente cu indici superiori si inferiori: (1) (2) (3) (4) (5) E E E E E --> --> --> --> --> E sub E sup E E sub E E sup E {E} a de si a ca Se observa ca gramatica nu pune in evidenta proprietatile asociativitate si prioritatile relative ale operatorilor sub sup. Se observa insa . Acest fapt poate ridica probleme in situatia generarii automate a translatoarelor.-------+---+---+---+---+--0 s2 s3 1 -------+---+---+---+---+--1 acc -------+---+---+---+---+--2 s2 s3 4 -------+---+---+---+---+--3 r3 r3 -------+---+---+---+---+--4 s5 r2 -------+---+---+---+---+--5 s2 s3 6 -------+---+---+---+---+--6 r1 r1 ---------------------------+ (1) S --> iSeS (2) S --> iS (3) S --> a De exemplu pentru sirul de intrare iiaea se obtine urmatoarea evolutie a analizorului : stiva intrare ---------------+-------------0 iiaea$ ---------------+-------------0i2 iaea$ ---------------+-------------0i2i2 aea$ ---------------+-------------0i2i2a3 ea$ ---------------+-------------0i2i2S4 ea$ ---------------+-------------0i2i2S4e5 a$ ---------------+-------------0i2i2S4e5a3 $ ---------------+-------------0i2i2S4e5S6 $ ---------------+-------------0i2S4 $ ---------------+-------------0S1 $ +-----------------------------Se observa ca ambiguitatea acceptata a acestor gramatici a permis reducerea numarului de productii ale gramaticii impunind insa o interventie directa pentru rezolvarea conflictelor. Sa mai consideram un caz in care utilizarea unei gramatici ambigue este utila.

a --> --> --> --> --> --> E sup.{E} .E sup E .{E} .a I6 : E E E E --> --> --> --> E. sup E E sup E. sub E E. --> a.E sub .E sup . sub E sup E E.E sub E sup E .{E} --> . si E --> E sup E. sub E E sub E. sub E E. Aceasi observatie este valabila pentru multimiile I8 si I11.} I7 : E --> E. sub E sup E E. I10 : E E E E E E E I11 : E E E E E --> --> --> --> --> --> --> --> --> --> --> --> E sub E sup.E sub E sup E --> . E. sup E {E. E. E --> . Aceasta productie are ca scop evidentierea faptului ca o expresie de forma a sub i sup 2 este reprezentata sub forma ai2 si nu ai2. Daca starea din virful stivei este 11 si in stiva s-a construit sirul E sub E sup E atunci trebuie sa se utilizeze productia E --> E sub E sup E. sup E E.E sub E sup E . sup E E.E sub E .a E E sup E E E Sa consideram de exemplu multimea I7 pentru care apar conflicte de tip deplaseaza / reduce pentru terminalele sub si sup deoarece nu sint definite proprietatile de asociativitate si prioritatile relative.E sub . E.E sub E . E . Daca se hotareste ca cele doua terminale au aceasi prioritate si sint asociative dreapta atunci pentru conflictul deplaseaza / reduce se va alege intodeauna actiunea deplaseaza. Sa consideram multimiile de elemente LR(0) pentru aceasta gramatica : I0 : E' E E E E E I1 : E' E E E I2 : E E E E E E I3 : E I4 : E E E E E E E I5 : E E E E E E --> --> --> --> --> --> --> --> --> --> --> --> --> --> --> --> .E sup E .E sub E --> .E .{E} . sub E E.a E.E} . . sub E sup E E sub E sup E. cel al productiilor de forma E sub E sup E. sub E E. E E sup.E sup E --> . sub E sup E E.existenta primei productii face ca si in acest caz gramatica sa ramina ambigua. sup E E sup E.{E} . sup E {. I9 : E --> {E}. Productia (1) pune in evidenta un caz special al productiilor (2) si (3). --> E sub. Multimea I11 genereaza in plus un conflict de tip reduce / reduce pentru simbolii terminali } si $ intre productiile E --> E sub E sup E. sub E sup E E E E E I8 : E E E E --> --> --> --> --> --> --> --> E sub E.E sup E .E sub E .E sub E sup E . Se observa insa ca in starea 11 nu se poate ajunge decit in urma urmatoarei succesiuni de stari : . E sup E --> E sub.a E.

3.2. Revenirea din eroare presupune cautarea unor conditii de continuare a analizei dupa intilnirea unei erori. Revenirea din eroare pentru analiza LR Erorile sint identificate in analiza LR atunci cind inspectindu-se tabela de actiuni se gaseste o intrare nedefinita.6.5.E sub E sup E +---+ +---+ +---+ +---+ +----+ +----+ 0 -----> 1 -----> 4 -----> 7 -----> 10 -----> 11 +---+ +---+ +---+ +---+ +----+ +----+ In timp ce pentru sirul E sup E succesiunea de stari este : E sup E +---+ +---+ +---+ +---+ 0 -----> 1 -----> 5 -----> 8 +---+ +---+ +---+ +---+ va rezulta urmatoarea tabela de analiza : actiune goto stare sub sup { } a $ E -------+-----+-----+---+---+---+---+--0 s2 s3 1 -------+-----+-----+---+---+---+---+--1 s4 s5 acc -------+-----+-----+---+---+---+---+--2 s2 s3 6 -------+-----+-----+---+---+---+---+--3 r5 r5 r5 r5 -------+-----+-----+---+---+---+---+--4 s2 s3 7 -------+-----+-----+---+---+---+---+--5 s2 s3 8 ---------------------------------------+ actiune goto stare sub sup { } a $ E -------+-----+-----+---+---+---+---+--6 s4 s5 s9 -------+-----+-----+---+---+---+---+--7 s4 s10 r2 r2 -------+-----+-----+---+---+---+---+--8 s4 s5 r3 r3 -------+-----+-----+---+---+---+---+--9 r4 r4 r4 r4 -------+-----+-----+---+---+---+---+--10 s2 s3 11 -------+-----+-----+---+---+---+---+--11 s4 s5 r1 r1 ---------------------------------------+ Daca se incearca transformarea gramaticii in scopul eliminarii ambiguitatii lucrurile sint mult mai dificile. O abordare posibila consta din cautarea in stiva a unei stari s pentru care .

) sau end).A] incercindu-se continuarea analizei. se afiseaza mesajul "lipseste operand" e2 : /* procedura apelata in starile 0. o instructiune sau un bloc (discutind in termeni de limbaje de programare).4. de exemplu : o expresie. Procedurile de tratare a erorilor vor fi legate de intrarile nedefinite in tabela actiuni. s E {0.. In acest caz se observa ca se incearca izolarea structurii sintactice in care apare eroarea pentru ca se observa ca s-a recunoscut o parte din sirul derivat din A dupa care s-a identificat o eroare.4.2.1. Aceste modificari nu fac decit sa intirzie diagnosticarea erorii.este definita o intrare in tabela goto pentru un neterminal care reprezinta o unitate sintactica semnificativa . Sa consideram de exemplu tabela de analiza pentru gramatica expresilor aritmetice : actiune goto stare a + * ( ) $ E -------+---+---+---+---+---+---+--0 s3 e1 e1 s2 e2 e1 1 -------+---+---+---+---+---+---+--1 e3 s4 s5 e3 e2 acc -------+---+---+---+---+---+---+--2 s3 e1 e1 s2 e2 e1 6 -------+---+---+---+---+---+---+--3 r4 r4 r4 r4 r4 r4 -------+---+---+---+---+---+---+--4 s3 e1 e1 s2 e2 e1 7 -------+---+---+---+---+---+---+--5 s3 e1 e1 s2 e2 e1 8 -------+---+---+---+---+---+---+--6 e3 s4 s5 e3 s9 e4 -------+---+---+---+---+---+---+--7 r1 r1 s5 r1 r1 r1 -------+---+---+---+---+---+---+--8 r2 r2 r2 r2 r1 r2 -------+---+---+---+---+---+---+--9 r3 r3 r3 r3 r3 r3 -------+---+---+---+---+---+---+--10 r3 r3 r3 r3 r3 r3 -------+---+---+---+---+---+---+--11 r5 r5 r5 r5 r5 r5 -----------------------------------+ (1) (2) (3) (4) E E E E --> --> --> --> E + E E * E (E) a Se observa ca intrarile de eroare au fost inlocuite pentru starile pentru care sint specificate reduceri cu intrari de reducere.4 si 5 cind se intilneste o paranteza inchisa neechilibrata */ se renunta la paranteza inchisa din sirul de intrare . Se cauta apoi un terminal pe sirul de intrare care poate sa urmeze dupa simbolul neterminal respectiv (de exemplu . Procedurile de tratare a erorilor sint : e1 : /* procedura apelata in starile 0.2.2. Ceeace a mai ramas din sir este la intrare si trebuie sa fie ignorat.a] = 3. eroarea va fi diagnosticata inainte ca o alta deplasare sa aiba loc.5 cind se asteapta inceperea unui operand si este intilnit un operator */ se introduce in stiva un simbol a fictiv si starea 3 corespunzatoare (goto[s. Se va considera ca s-a recunoscut neterminalul respectiv (fie el A) si se executa goto[s.5}).

Ravi Sethi.se afiseaza mesajul "lipseste paranteza deschisa" e3 : /* procedura apelata in starea 1 sau 6 cind in loc de un operator se intilneste un simbol a sau o paranteza deschisa */ se introduce + si 4 in stiva se afiseaza mesajul "operator absent" e4 : /* procedura este apelata in starea 6 la intilnirea sfirsitului sirului pentru ca in starea 6 se asteapta un operator sau o paranteza inchisa */ se introduce o paranteza inchisa si starea 9 in stiva se afiseaza mesajul "lipseste paranteza inchisa" Pentru sirul a+) secventa de miscari ce se obtine este : stiva intrare ------------+-----------0 a+)$ ------------+-----------0a3 +)$ ------------+-----------0E1 +)$ ------------+-----------0E1+4 )$ "lipseste paranteza deschisa" ------------+-----------0E1+4a3 $ "lipseste operand" ------------+-----------0E1+4E7 $ ------------+-----------0E1 $ Bibliografie Alfred V.Hall William M. and Tools Addison Wesley. Christos H. Translation and Compiling Prentice. Gerhard Goos Compiler Construction Springer Verlang Harry R. Ullman Compilers Principles. Jeffrey D. Ullman The Theory of Parsing. 1986 Alfred V. Papadimitriou Elements of the Theory of Computation Prentice Hall. Aho. Harrison Introduction to Formal Language Theory . Techniques. Lewis. Aho. 1981 Michael A. Waite. Jeffrey D.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->