Principiul analizei sintactice descendente nerecursive
Este acelasi ca si in cazul analizorului cu descendenti recursivi, in sensul ca procesul de analiza se realizeaza prin derivari succesive ale neterminalelor, incepand cu radacina, dar implementarea este diferita, si anume, derivarile nu se transpun ca secvente de cod, ci se bazeaza pe structuri de date in care se indica ramurile de derivare.
Structurile folosite sunt:
Pe baza simbolului aflat in varful stivei si a simbolului curent din sirul de intrare, analizorul decide care din urmatoarele actiuni se vor executa:O tabela de analiza, ale carei intrari contin cate o productie a gramaticii (dupa care se face derivarea la un moment dat).
O stiva de analiza in care se introduc simboluri ale gramaticii.
Restrictiile care se impun asupra unei gramatici, in vederea aplicarii analizei de tip LL(1) sunt aceleasi ca si in cazul analizei cu descendenti recursivi, si anume:
Algoritmul de analiza
Vom nota:
Algoritmii de construire a tabelei de analiza
Tabela de analiza va avea un numar de linii egal cu numarul neterminalelor si numarul de coloane egal cu numarul terminalelor (inclusiv simbolul $).
Notand cu G gramatica de analizat si cu TabSIN tabela de analiza, completarea elementelor acesteia se va face dupa urmatoarea procedura:Completarea tabelei de analiza
procedure complTabSIN isO multime PRIM(alfa) cuprinde toate terminalele a care satisfac conditia:
for fiecare relatie Aalfa din G do
for fiecare a din PRIM(alfa) do
TabSIN[A, a] = Aalfa
endfor
if Epsilon este in PRIM(alfa) then
for fiecare b din URM(A) do
TabSIN [A, b] = Aalfa
endfor
if Epsilon este in URM(A) then
TabSIN [A, $] = Aalfa
endif
endif
endfor
for fiecare TabSIN [A, a] necompletat do
*completeaza TabSIN [A, a] cu apel de eroare
endfor
end complTabSIN
alfa a beta
O multime URM(A) contine toate terminalele a care pot sa apara imediat in dreapta lui A, intr-un sir oarecare al limbajului sursa:
S alfa A a beta
Calculul acestor multimi se face conform algoritmilor
de mai jos:
Calculul multimilor PRIM
procedure calculPRIM(alfa) is
*initializeaza PRIM(alfa) cu multimea vida
if alfa este format dintr-un singur simbol X then
if X este terminal then
PRIM (X) = { X }
else
for toate relatiile Xa beta do
*adauga a la PRIM (X)
endfor
if exista XEpsilon then
*adauga Epsilon la PRIM (X)
endif
for toate relatiile XY1Y2 . . .Yn, cu Y1 - neterminal do
*adauga PRIM (Y1) - { Epsilon } la PRIM(X)
gata = false
i = 2
repeat
if Epsilon nu este in PRIM(Yi-1) then
gata = true
else
*adauga PRIM (Yi ) - { Epsilon } la PRIM (X)
i = i + 1
if i > n then
*adauga Epsilon la PRIM(X)
endif
endif
until i > n or gata
endfor
endif
else
*consideram ca alfa este de forma X1X2 . . . Xm
*adauga PRIM (X1)- { Epsilon } la PRIM (alfa )
i = 2
gata = false
repeat
if Epsilon nu este in PRIM (Xi-1) then
gata = true
else
*adauga PRIM (Xi ) - { Epsilon } la PRIM (alfa)
i = i + 1
if i > m then
*adauga Epsilon la PRIM (alfa)
endif
endif
until i > m or gata
endif
end calculPRIM
Calculul multimilor URM
procedure calculURM(A) is
*initializeaza URM(A) cu multimea vida
if A este radacina gramaticii then
*adauga Epsilon la URM(A)
endif
for toate productiile Balfa A beta do
*adauga PRIM(beta)- { Epsilon } la URM(A)
if beta este sirul vid or Epsilon este in PRIM(beta) then
*adauga URM(beta) la URM(A)
endif
endfor
end calculURM(A)
Multimile PRIM si URM
corespunzatoare fiecarui neterminal al gramaticii se pot reprezenta folosind
cate o tabela, TabPRIM, respectiv TabURM, cu
elemente de tip boolean, indexate pe verticala cu neterminale, iar pe orizontala
cu terminale; un element de coordonate [A, a] oarecare
al acestor tabele va contine valoarea true daca a este
in PRIM(A), respectiv a este in URM(A),
si
false in caz contrar.
Daca, in urma completarii tabelei de analiza, se obtin
intrari
multiple (care contin doua sau mai multe productii), inseamna
ca gramatica respectiva este ambigua. In cazul limbajelor de programare
cunoscute, de cele mai multe ori, la o analiza atenta a gramaticii, proiectantul
poate stabili care dintre productii poate ramane in tabela, la elementul
in cauza.
Desfasurarea lucrarii
Se va realiza un generator de analizor LL(1) care sa primeasca la intrare productiile unei gramatici date de conducatorul lucrarii (sau cea din Anexa B). Analizorul rezultat va tipari la executie, la fiecare pas, urmatoarele informatii: