Obtinerea informatiilor de tip
Informatiile de tip se extrag in decursul analizei declaratiilor si a expresiilor si pot fi considerate ca atribute atasate simbolurilor gramaticale implicate in declaratii si expresii. Obtinerea propriu-zisa a acestor informatii are loc fie prin preluarea lor din TS, fie prin receptarea lor de la analizorul lexical, in momentul detectarii terminalelor identificator sau constanta.
Transmiterea informatiilor de tip spre punctele din analizorul sintactic unde urmeaza sa se execute rutine de analiza semantica se poate realiza prin intermediul:
a. Atrib_tip - indica tipul (simplu) pe care il are o constanta, o variabila sau o expresie. Valoarea acestui atribut poate fi: 'intreg', 'real' sau 'caracter'.
b. Atrib_lvalue - poate lua una din valorile: 'adresa ' sau 'valoare', indicand daca o anumita expresie are atasata o adresa stabila de memorie (expresia este formata dintr-o variabila declarata in sectiunea var, sau dintr-un parametru formal declarat cu var), respectiv daca expresia reprezinta un rezultat intermediar, aflat temporar in memorie. Acest atribut este necesar pentru verificari ale parametrilor, in cazul apelurilor de subprograme. El permite detectarea situatiilor in care unui parametru formal declarat cu var (transmis prin adresa) ii corespunde un parametru real care nu are o adresa stabila (nu este o expresie l-value, daca ar fi sa folosim terminologia din limbajul C). Exemplu:
var A : integer;
procedure P (var X : integer);
beginX := . . .end; { P }
begin {program principal}P(12); {1}end.
P( A + 2 ); {2}
P(A); {3}
In secventa de mai sus apelurile din liniile notate cu {1} si {2} sunt incorecte din punct de vedere al modului de transmitere a parametrilor, in timp ce apelul din linia {3} este corect.
Dupa cum se vede, am convenit ca valorile atributului Atrib_lvalue sa fie aceleasi cu cele ale campului 'tip_transmisie' din nodurile listei LISTA_PAR din TS, pentru a usura rutina de verificare a parametrilor (v. Apeluri de subprograme si Factori).c. Atrib_val - se foloseste in cazul declaratiilor de constante (sectiunea const) si indica valoarea atribuita unei constante. O asemenea valoare este calculabila la compilare si se obtine prin evaluarea unei expresii statice (v. Evaluarea expresiilor statice).
Reguli semantice referitoare la concordanta tipurilor
In cele ce urmeaza vom adopta urmatoarele conventii legate
de tipuri:
Expresii relationaleExpresii aditiveE1 oprel E2 Regula este:
{ Atrib_tip(E1), Atrib_tip(E2) }{ 'intreg', 'real' } sau
Atrib_tip(E1) = Atrib_tip(E2) = 'caracter'Tipul rezultatului unei expresii relationale va fi:
(convenim ca rezultatul unei expresii relationale este 1 sau 0, dupa cum relatia definita de oprel este sau nu satisfacuta ). Atrib_tip(E1oprel E2) = 'intreg'
E1 opad E2Regula este:
{ Atrib_tip(E1), Atrib_tip(E2)} { 'intreg', 'real' }
Tipul rezultatului este:
if Atrib_tip(E1) = Atrib_tip(E2) then
endifAtrib_tip(E1 opad E2) = Atrib_tip(E1)
elseAtrib_tip
(E1 opad E2) = 'real'
Expresii multiplicative
Operatii de atribuireE1 opmul E2 Regula este:
if opmul in {div, mod} then
else*trebuie ca Atrib_tip(E1) = Atrib_tip(E2) = 'intreg'
*trebuie ca {Atrib_tip(E1), Atrib_tip(E2)}{'intreg', 'real'}
endif Tipul rezultatului este:if opmul in {div, mod} then
elseAtrib_tip(E1 opmul E2) = 'intreg'
elseif opmul = '/' then
E2) = 'real'Atrib_tip(E1 opmul
*se aplica regula pt. tipul rezultatului de la Expresii aditive
endif endif Facem conventia ca , in cazul utilizarii operatorului '/' (impartire reala) pentru operanzi intregi, acestia sa fie convertiti la tipul real.
Instructiunea for
V := ERegula este:
( Atrib_tip(V) = Atrib_tip(E) sau
( Atrib_tip(V) = 'real' si Atrib_tip(E) = 'intreg' ) ) si
( Atrib_lvalue(V) = 'adresa' )Se face conventia ca daca tipul membrului stang este 'real' si tipul membrului drept este 'intreg', acesta din urma se converteste la tipul 'real'.
Variabile indexatefor V := E1 to/downto E2 step E3 do I Regula este ca
(Atrib_tip(V) = Atrib_tip(E1) = Atrib_tip(E2) = Atrib_tip(E3) = 'intreg') si
Atrib_lvalue(V) = 'adresa'
Declaratii de tablouriid[E] Daca notam cu loc_id locul in TS ocupat de simbolul id, regula este:
TS[loc_id].CLASA = 'nume de tablou' si Atrib_tip(E) = 'intreg'.
Tipul unei variabile indexate este :
Atrib_tip( id[E] ) = TS[loc_id].TIP.
array [E1 .. E2] of T Regula este:
Atrib_tip(E1) = Atrib_tip(E2) = 'intreg' si
Atrib_val(E1) <= Atrib_val(E2)
Referinte ale campurilor de structuri
id1. id2 Daca notam cu loc1, respectiv cu loc2 pozitiile din TS ocupate de id1 si id2, atunci regula este:
TS[loc1].CLASA = 'nume de structura ' si
TS[loc2].CLASA = 'nume de camp' si
exista un nod in TS[loc2].LISTA_REC care face trimitere spre loc1Tipul unei asemenea variabile va fi:
Atrib_tip( id1. id2 ) = TS[loc2].TIP.
Apeluri de subprograme
Instructiunea caseid ( E1, E2, . . . , En ) Notand cu loc_id locul din TS ocupat de id, se vor impune urmatoarele conditii:
Convenim ca, in cazul in care un parametru formal este de tip 'real', iar parametrul de apel corespunzator este de tip 'intreg', valoarea acestuia din urma sa fie convertita la tipul 'real'.
- TS[loc_id].CLASA = 'nume functie' sau 'nume procedura ', dupa cum apelul apare intr-o expresie, respectiv intr-o instructiune apel de procedura;
- TS[loc_id].NR_PAR = n;
- Atrib_tip(Ei) = TS[loc_id].LISTA_PARi.tip_param sau
(Atrib_tip(Ei) = 'intreg' si TS[loc_id].LISTA_PARi.tip_param ='real' si TS[loc_id].LISTA_PARi.tip_transmisie = 'valoare' ), pentru i = 1 . . n.
Se precizeaza ca LISTA_PARi reprezinta nodul de pe pozitia i, din lista LISTA_PAR.- Atrib_lvalue(Ei) = TS[loc_id].LISTA_PARi.tip_transmisie, pentru i = 1 . . n.
In cazul apelurilor de functii tipul rezultatului va fi:
Atrib_tip( id( E1, E2, . . . , En )) = TS[loc_id].TIP
Atrib_tip(E) = Atrib_tip (Ci,j), pt. i = 1..m, j = 1..ni
In cele ce urmeaza , partea de analiza a expresiilor va
fi prezentata utilizand inserarea de marcaje in productiile gramaticale
si indicand actiunile semantice corespunzatoare.
Se realizeaza prin intermediul atributului Atrib_val.
Productiile implicate sunt cele care decurg din simbolul Sectiune_const.
Expresii aditive
E1 opad E2 Atrib_val( E1 opad E2 ) = Atrib_val(E1) opad Atrib_val(E2)
Expresii multiplicative
E1 opmul E2 Determinarea lui Atrib_val se face ca la Expresii aditive, inlocuind opad cu opmul. In cazul impartirilor se vor face verificari pentru a evita impartirea cu 0.
Factori statici
Pozitionarea marcajelor si tratarea acestora pentru evaluarea expresiilor statice sunt explicate pe larg in Anexa D.FS -> id | const | ( E ) Daca factorul este o constanta , atunci Atrib_val ia valoarea constantei respective (memorata in TAB_CONST).
Daca factorul este un identificator, atunci se verifica daca TS[loc_id].CLASA = 'nume constanta ' (unde loc_id este locul din TS ocupat de identificator) si daca da, atunci Atrib_val(F) = TAB_CONST[TS[loc_id].VAL ].
Daca factorul este o expresie intre paranteze, atunci Atrib_val(F) = Atrib_val(E).
Atribuiri
Instr_atrib -> Variabila := Expresie1
Variabila -> identificator1 |
identificator2 [Expresie2 ] |
identificator3 . identificator4
Notand cu tipv si tipe_i valorile lui
Atrib_tip
determinate pentru Variabila, respectiv pentru
Expresiei (i=1..2),
avem:
loc1 = Cauta _TS(identificator1)
select TS[loc1].CLASA of
'nume de variabila ',
'nume de parametru' :
endselecttipv = TS[loc1].TIP
'nume de functie' :
if loc1 <> ST_BLOC[VSTB]
then
default:
*eroare 'nu se poate atribui decat numele functiei curente'
else
tipv = TS[loc1].TIP
endif*eroare 'acest simbol nu este l-value'
*fie loc2 indicele intrarii din TS corespunzatoare lui
identificator2
if TS[loc2].CLASA <> 'nume
de tablou' then
*eroare ' identificator2 nu este
nume de tablou'
else
if tipe_2 <> 'intreg' then
endif
*eroare 'indicele trebuie sa fie de tip intreg'
else
tipv = TS[loc2].TIP
endif
*fie loc3 si loc4 indicii in TS unde se afla
identificator3,
respectiv identificator4
if TS[loc3].CLASA <> 'nume de
structura ' then
*eroare 'identificator3 nu este
nume de structura'
else
if TS[loc4].CLASA = 'nume
de camp' then
endif
*cauta in TS[loc4].LISTA_REC un nod cu continutul
= loc3
else
if nu s-a gasit then
*eroare 'identificator4 nu este
camp al lui identificator3'
else
tipv = TS[loc4].TIP
endif*eroare 'identificator4 nu este
camp al lui identificator3'
endif
if tipv <> tipe_1 then
if tipv = 'caracter' or
tipe_1 = 'caracter' or tipv = 'intreg' then
endif*eroare 'nu se poate converti tipe_1 la tipv'
endif
Notam cu:
Expresii multiplicative
Se trateaza in mod similar cu cele aditive, aplicand
insa regulile enuntate pentru operatiile multiplicative
Factori
Lista_expresii -> Expresie3 |
Notam cu :
Stabilirea marcajelor si a rutinelor aferente pentru analiza
tipurilor la instructiunile for si case este propusa studentilor
ca exercitiu
Desfasurarea lucrarii
Dupa modelul procedurilor prezentate in capitolul Analiza expresiilor si in
Anexa D, se va completa compilatorul realizat pana acum cu rutinele de
analiza a tipurilor. In vederea testarii se vor alege texte sursa care
sa contina in principal definitii si referiri de constante, atribuiri,
apeluri de subprograme, expresii de diverse grade de complexitate, instructiuni
for. Pentru aceste categorii sintactice se vor tipari informatii
legate de atributele Atrib_tip, Atrib_lvalue si Atrib_val,
precum si mesaje privind eventualele erori semantice semnalate la analiza
de tip.
Pentru a realiza integrarea rutinelor semantice cu analizoarele
sintactice realizate in lucrarile anterioare se vor utiliza modelele prezentate
in Anexa D.