Sunteți pe pagina 1din 68

Construc]ia compilatoarelor folosind

Flex [i Bison
Anthony A. Aaby
Walla Walla College
cs.wwc.edu
aabyan@wwc.edu
Popa Dan
Universitatea Bac\u
www.ub.ro
popavdan@yahoo.com, dpopa@ub.ro
Versiunea din 4 august 2005
1
Copyright 2003 Anthony A. Aaby
Walla Walla College
204 S. College Ave.
College Place, WA 99324
E-mail aabyan!""c.e#$
%a&e' (o$rce( available by re)$e(t.
&hi( material may be #i(trib$te# only ($b*ect to the term( an# con#ition(
(et +orth in the ,pen P$blication %icen(e, v-.0 or later .the late(t ver(ion i(
pre(ently available at http//""".opencontent.org/openp$b
&hi( boo0 i( #i(trib$te# in the hope it "ill be $(e+$l, b$t "itho$t any "arranty1
"itho$t even the implie# "arranty o+ merchantability or +itne(( +or a
partic$lar p$rpo(e.
&he a$thor enco$rage( "i#e #i(trib$tion o+ thi( boo0 +or per(onal an# commercial
$(e, provi#e# the above copyright notice remain( intact an# the metho#
a#here( to the provi(ion( o+ the ,pen P$blication %i(cen(e locate# at
http//""".opencontent.org/openp$b
2n ($mmary, yo$ may copy an# #i(trib$te thi( boo0 +ree o+ charge or +or a
pro+it. 3o e4plicit permi((ion i( re)$ire# +rom the a$thor +or repro#$ction o+
thi( boo0 in any me#i$m, phy(ical or electronic.
3ote, #erivative "or0( an# tran(lation( o+ thi( #oc$ment m$(t incl$#e the
original copyright notice m$(t remain intact.
Versiunea `n limba romna este tradus! [i adaptat! de "an #opa $
popav#an!yahoo.com, #popa!$b.ro. %m f!cut de asemenea o serie de
rectific!ri [i corecturi& %m unificat nota]iile pentru codul generat [i instruc]i'
unile ma[inii (irtuale& )oate fi[ierele surs! au fost rescrise la calculator [i
toate programele au fost testate& "atorit! adapt!rii$ o serie de por]iuni din
text au fost rescrise iar paragrafe `ntregi cu explica]ii au fost ad!ugate&
*arcarea lor folosind caractere italice ar fi `nc!rcat inutil textul dar cititorul
interesat poate compara cele dou! edi]ii$ engle+! [i romn! pentru a (edea
ce modific!ri [i ad!ugiri s'au f!cut cu oca+ia traducerii [i adapt!rii& , parte
din anexele (ersiunii `n limba engle+! nu au fost incluse `n aceast!
(ersiune&
Cop-rig.t'ul pentru edi]ia `n limba romn!/ "an #opa 020051
2
C$prin(
2n loc de moti(a]ie 5
1 3ntroducere 4
2 %nali+orul sintactic 0#arser'ul1 15
5 6caner'ul 0%nali+orul lexical1 17
4 Contextul 25
5 ,ptimi+area 55
8 *a[ini Virtuale 54
4 9enerarea Codului 45
: ,ptimi+area de cod dup! generare 55
7 ;ecturi suplimentare 54
10 <xerci]ii 58
%nexa %/ ;imba=ul 6imple ' 3mplementarea complet! &&5:
%&1 #arserul/ 6imple&- & & & & & & & & & & & & & & & & & & & & & & & & & 5:
%&2 3ndica]ii de lucru & & & & & & & & & & & & & & & & & & & & & & & & & & & 81
%&5 6canerul/ 6imple&lex & & & & & & & & & & & & & & & & & & & & & & & &82
%&4 )abela de simboluri/ 6)&. & & & & & & & & & & & & & & & & & & & 85
%&5 9eneratorul de cod/ C9&. & & & & & & & & & & & & & & & & & & & &84
%&8 *a[ina cu sti(!/ 6*&. & & & & & & & & & & & & & & & & & & & & & & &85
%&4 >n exemplu de program/ test?simple & & & & & & & & & & &84
%nexele edi]iei de limb! engle+! neincluse `n aceast! edi]ie electronic! /
B ;ex@Flex
B&1 ;ex@Flex <xamples & & & & & & & & & & & & & & & & & & & & & & & & & &
B&2 ).e ;ex@Flex 3nput File & & & & & & & & & & & & & & & & & & & & & & &
B&5 ).e 9enerated 6canner & & & & & & & & & & & & & & & & & & & & & &
B&4 3nterfacing Ait. Bacc@Bison & & & & & & & & & & & & & & & & & & & &
C Bacc@Bison
C&1 %n ,(er(ieA & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &
C&2 % Bacc@Bison <xample & & & & & & & & & & & & & & & & & & & & & &
C&5 ).e Bacc@Bison 3nput File & & & & & & & & & & & & & & & & & & & &
C&4 Bacc@Bison ,utput/ t.e #arser File & & & & & & & & & & & & &
C&5 #arser C';anguage 3nterface & & & & & & & & & & & & & & & & & &
C&8 "ebugging Bour #arser & & & & & & & & & & & & & & & & & & & & & &
C&4 6tages in >sing Bacc@Bison & & & & & & & & & & & & & & & & & & &
5
)itlul original/ Compiler Construction using Flex and Bison
Cop-rig.t C 2005$ %nt.on- %&%ab-
Cop-rig.t C 2005$ #opa "an$
0 pentru textul re+ultat din traducerea `n limba romn! [i por]iunile explicati(e inserate1
Contribu]ia autorilor/
%nt.on- %& %ab-/ `ntregul (olum cu excep]ia paragrafelor care nu se g!sesc `n edi]ia original!$ sursele
programelor cu comentarii `n limba engle+!$ sursele din anex!
#opa "an/ paragrafele explicati(e care lipsesc din edi]ia `n limba engle+!$ sursele programelor comentate
`n limba romn!$ eratele cuprinse `n text$ nota]iile unificate$ rularea [i (erificarea programelor$ corecturile
surselor din anex!$ corectura final!$ traducerea [i adaptarea
#opa "an
#anselelor 10$ 6c %$ <t 1$ %pt 5$ Bac!u$ Domnia
tel/ 0254 582288
e'mail/ popa(dan!-a.oo&com$ dpopa!ub&ro
#opa "an E Cartea prin e'mail
%cest (olum poate fi solicitat gratuit$ `n format &pdf$ la adresa publica de e'mail a autorului/
e'mail/ popa(dan!-a.oo&com
;a cerere$ `n situa]ii de necesitate$ putem trimite contra unei taxe de multiplicare [i expedi]ie exemplare
multiplicate&
"escrierea C3# a Bibliotecii Fa]ionale a Domniei
%nt.on- %& %ab-
Construc]ia compilatoarelor folosind Flex [i Bison @ %nt.on- %& %ab-$ "an #opa '
Bac!u/ 2005 $ 8: pg
Bibliogr&
36BF 745'0'04015'5
3& %ab-$%nt.on- %&
33& #opa$ "an
4
2n loc de moti(a]ie
"e ce s! scriu o carte despre compilatoare$ interpretoare $Flex [i Bison$ `n limba
romn!$ `n anii primului cincinal al mileniului al doilea G 6unt de actualitate G Folosesc
ele cui(a G 6au r!mn un simplu exerci]iu academic ori te.nic$ destinat profesorilor de
teoria compilatoarelor [i .acHerilor 0ade(!ra]ilor .acHeri$ acei exper]i autentici `n
compilatoare care sunt `n stare s!']i in(ente+e un limba= de pe a+i pe mine sau s!']i
ascund! un (irus `ntr'un compilator astfel ca el s! genere+e programe de login IsparteJ$
c.iar dac! le compile+i din nou1 G "e ce o asemenea carte este necesar! oportun! [i
cui ar folosi G Ce moti(e sunt pentru scrierea ei G
3at!'le$ `ntr'o ordine oarecare$ a[a cum mi'au (enit Kla prima strigareJ/
11 ;inux'ul se r!spndeste rapid$ num!rul de utili+atori crescnd (ertiginos cu cifre `ntre
8L [i 58L pe an 0num!rul depinde de categoria de utili+atori$ utili+atori casnici sau
manageri de ser(ere1& #entru acei utili+atori de ;inux care$ uneori `n ciuda (rstei$ mai
au dorin]a de a `n(!]a$ de a se bucura ca ni[te copii care descoper! 9oogle'ul$ pentru
ei$ cei care uneori .abar n'au ce ser(icii le pot aduce Flex'ul [i Bisonul$ merit! s!
traduc$ s! scriu$ s! complete+ aceast! carte& %u o [ans! `n plus s! afle ce mai con]ine
distribu]ia lor fa(orit! de ;inux& Fu scriu care distribu]ie$ deoarece ma=oritatea distribu]i'
ilor de ;inux pe care le'am consultat 0DedMat 4&2$ 5&2$ 8&0$ 8&1$ 8&2$ 4&0$ 4&2 $ Corel
;inux $ *andraHe ;inux :&0$ :&1$ :&2$ 7$ 10 [i altele1 includ pac.etele Flex [i Bison&
21 Flex [i Bison nu sunt numai instrumente de scriere a compilatoarelor& Flex'ul e un
generator de anali+oare lexicale deci o unealt! pentru `mp!r]it texte `n Icu(inteI 0sau
litere sau alte grup!ri de simboluri cu structur! specific!1 [i de executat ac]iuni la
`ntlnirea lor& Bisonul este c.iar mai puternic/ poate prelucra date imbricate$ a(nd
structuri [i substructuri$ specificate printr'o gramatic!& <ste un generator de parsere
0anali+oare sintactice1 care pot fi dotate [i cu reguli semantice$ ceea ce `l face un
(eritabil generator de compilatoare&
51 Flex'ul [i `n mai mic! m!sur! Bison'ul pot fi de folos [i altor categorii de personal&
2ntr'un num!r din re(ista #C Deport$ un alt generator de anali+oare lexicale era
pre+entat printr'un exemplu care re+ol(a o problem! spinoas! te.noredactorilor/
con(ersia textelor de la un font la altul sau la standardul >)F& Cei care s'au lo(it de
problema diacriticelor limbii romne$ problem! pentru care exist! cte IbordeieI attea
Iobiceie de scriereI ' a se citi fonturi sau standarde$ [i au primit nu o dat! mail'ul unui
[ef sup!rat c! textul nu se (ede cu diacritice pe computerul s!u$ (or `n]elege
actualitatea problemei&
41 %]i putea fi de asemenea cititori ai unei asemenea c!r]i dac! dori]i s! manipula]i date
structurate ori (re]i s! ob]ine]i (ite+! la prelucr!ri ale unor anumite ba+e de date
5
reali+ate cu N*; $ f!r! a mai `n(!]a N*; [i `n condi]iile `n care aplica]ia (a fi reali+at! cu
un compilator de limba= C&
51 %lte probleme banale pe fond dar relati( dificil de abordat cu mi=loace clasice [i
totodat! adesea `ntlnite la concursurile pentru posturi de programatori se re+ol(! u[or
cu Flex [i Bison& "intre ele amintim crearea unui calculator e(aluator de expresii
numerice cu parante+e $ 0un asemenea modul softAare ar ferici orice utili+ator de
produs de contabilitate$ dar admit c! poate fi reali+at [i altfel dect cu un generator de
compilatoare1 sau clasica problem! de traducere care const! `n a genera pentru un
num!r `n cifre transcrierea lui `n litere& %ceste probleme au [i alte solu]ii dar dac!
reali+a]i o aplica]ie contabil! cu ba+e de date *-6O; pe platform! ;inux poate ('ar
interesa [i problemele de mai sus$ mai ales dac! programa]i `n C sau CPP&
81 <xist! o mul]ime de generatoare de compilatoare mai sofisticate dec!t perec.ea
Flex$ Bison$ unele folosite la %cademie sau `n medii uni(ersitare& <xist! [i metode de
specificare mai e(oluate 0de exemplu Viena "efinition *et.od1& "in nefericire ori softul
este inaccesibil ma=orit!]ii cititorilor$ ori are licen]! proprietar!$ ori rulea+! pe cine [tie ce
computer 6un 6parc 6tation pe care nu'l a(em la dispo+i]ie noi$ utili+atoriui de #C'uri&
,ri pur [i simplu nu putem g!si `n Domnia softAare'ul ori documenta]ia& Combina]ia
;inux plus Flex plus Bison plus 9CC 0compilatorul 9F>$ fost 9F> C Compiler1 r!mne
deocamdat! generatorul de compilatoare cu r!spndirea cea mai larg! [i de[i exist!
(oci care afirm! c! re+ol(! doar :0L din problem!$ este totu[i `ndr!git! de
programatorii care ador! s! se afirme scriind ei ct mai mult cod&
41 "ac! sunte]i student la un curs de compilatoare sau doctorand la un `ndrum!tor care
se ocup! de construc]ia limba=elor$ dac! sunte]i frustrat c! la finalul cursului n'a]i f!cut
`nc! un compilator$ fie [i unul ct de mic$ pentru un limba= orict de simplu [i [ti]i s! da]i
cte(a comen+i unui sistem ;inux atunci aceast! carte e pentru dumnea(oastr! cu
siguran]!& Fu pot s! (! descriu emo]ia scrierii primului progr!mel care (a rula pe
interpretorul dumnea(oastr! sau (a fi compilat cu compilatorul dumnea(oastr!& Qi mai
ales satisfac]i'a care o (e]i sim]i (!+nd c! rulea+! sau se compilea+! [i se execut! f!r!
erori& V'o spune un fost absol(ent al primei serii de la o facultate de 3nformatic!$ serie
n!scut! prin transformarea uneia din cele de la sec]iile Faculta]ii de *atematic!& Ca
student re'u[isem performan]a de a termina facultatea de 3nformatic! f!r! s! fac practic
nici un compilator RRR *oti( pentru care dedic aceast! carte [i fo[tilor colegi de an [i fo
[tilor mei profesori$ `ncep!torii de alt! dat! 0preparatori$ asisten]i etc1$ speciali[tii de
ast!+i&
8
Capitolul 1
3ntroducere
>n compilator este `n esen]! un program traduc!tor ce transform! programe scrise `ntr'
un limba= surs! `n ec.i(alentele lor scrise `ntr'un limba= obiect& ;imba=ul surs! este de
obicei un limba= de programare de ni(el `nalt iar limba=ul obiect este de obicei limba=ul
ma[in! al computerului& "in punct de (edere pragmatic putem afirma c! prin translator
0compilator1 se define[te o anume semantic! a limba=ului de programare& )ranslatorul
transform! opera]iile date `n mod sintactic `n opera]ii ale modelului de calcul al unei ma
[ini (irtuale sau reale& %cest capitol arat! cum sunt folosite gramaticile independente de
context la construc]ia translatoarelor 0compilatoarelor1& "eoarece traducerea este
g.idat! de sintaxa limba=ului surs!$ traducerea aceasta este numit! Is-ntax'directed
translationI adic! Itraducere ba+at! pe sintax!I sau$ mai bine +is Itraducere diri=at! de
sintax!I&
"e ce este ne(oie de tot acest ansamblu de te.nici G V'a]i `ntrebat (reodat! de fac
compilatoarele anali+! sintactic! pe ba+a unei gramatici G "oar de dragul (erific!rii
sintaxei G Ficidecum R >n limba= de programare este ec.i(alent cu o mul]ime poten]ial
infinit! de programe& 6unt programele care se scriu `n el& "ac! am `ncerca s! definim
direct cum s'ar traduce ele$ lu`ndu'le rnd pe rnd$ nu ne'ar a=unge (e[nicia& "eci
trebuie g!site alte te.nici& )otu[i asemenea mul]imi infinite pot fi definite inducti( [i
st!pnite cu te.nici similare banalei induc]ii matematice de la liceu&
Ce este o defini]ie inducti(! G "au un exemplu ar.icunoscut/ numerele naturale nenule
se pot defini cu doar dou! elemente/ 1 [i functia succesor s0x1 care ni'l d! pe
succesorul lui x adic! pe x plus 1& %tunci numerele naturale nenule sunt/ 1$ s011$ s0s0111$
[amd& V'a]i prins G 6e `ncepe cu ceea ce matematicienii numesc ba+a induc]iei [i se
continu! dup! o regul! inducti(! care define[te ceea ce urmea+! func]ie de ceea ce
a(eam definit mai `nainte& %stfel putem st!pni numerele naturale$ `n infinitatea lor$
lucr!nd cu doar dou! elemente $ 0 [i func]ia s0x1$ cea care `n fapt descrie cum se ob]ine
un num!r mai complicat din precedentul&
"orim s! transcriem aceste numere ca sume de unit!]i G "at fiind c! numerele naturale
nenule sunt definite doar cu a=utorul a dou! elemente$ acum este simplu& )rebuie s!
definim cum se transcriu ca sume de unit!]i cele dou! elemente / 1 [i s0ceva1 unde
ceva la rndul s!u s'ar putea scrie tot ca o sum! de unit!]i& 3at! cele dou! reguli/
1 se transcrie prin 1$ IsumaI cu un termen
s0x1 se transcrie prin/ 1 plus transcrierea lui x
%dic! )011 este 1
iar )0s0x11 este 1 plus )0x1
Ct este$ de exemplu$ )0s0s0111 G
4
<ste 1 plus )0s0111 adic! 1plus 1 plus )011 adic! 1 plus 1 plus 1&
Conclu+ia/ #utem defini o traducere pe o mul]ime infinit! de elemente definite structural
inducti( dac! [tim cum se traduc/ elementele cele mai simple 0la un limba= de
programare structurat printre ele sunt instruc]iunile1 [i cum se traduc structurile
compuse& #entru structuri sunt date ni[te reguli care ne spun de obicei c! traducerea
structurii compuse se ob]ine imediat din traducerile structurilor componente& %cesta
este de altfel celebrul principiu compo+i]ional din semantic!&
"eci de ce a(em ne(oie de sintaxa limba=ului$ de structura lui sintactic! sau sc.ema$
arborele sintactic al acestuia G 0Care nu'i mai complicat dec!t ceea ce se f!cea la
[coala general!$ la gramatic! ' acele desene arborescenteR1 "eoarece nu'l putem
traduce altfel$ fiind infinit! mul]imea programelor posibile& >n mod de a st!pni
infinitatea aceasta este induc]ia matematic!$ definirea inducti(! iar pentru induc]ie a(em
ne(oie de ba+a induc]iei 0elemente de limba= despre care [tim direct cum se traduc1 [i
regulile inducti(e 0structurale1 care spun cum se traduce o structur! compus!$
traduc!ndu'i `nti componentele& %(nd traducerea definit! astfel$ inducti($ pe structuri
[i substructuri$ e clar c! primul pas al compil!rii e s! g!sesc$ aceste structuri& <xact a[a
ce(a face anali+a sintactic! R 3ar proiectantul unui limba= [i al unui compilator (a `ncepe
prin a scrie gramatica limba=ului$ acea descriere inducti(!$ structurat! a sintaxei
limba=ului `nsu[i& <i `i (a asocia pe urm! regulile semantice destinate a conduce
traducerea&
"efini]ie/ >n compilator este un translator al c!rui limba= surs! este un limba= de ni(el
`nalt 0apropiat omului$ cu cu(inte din limbile umane1 [i al c!rui limba= obiect este
apropiat de limba=ul ma[in! al computerului concret disponibil& Compilatorul tipic
parcurge urm!toarele fa+e [i fiecare fa+! prelucrea+! Ioutput'ulI$ ie[irea care se ob]ine
din fa+a precedent!/
Fa+a de analiz\ lexical\ 0IscanareaI textului `n c!utarea cu(intelor [i altor entit!]i1
grupea+! caracterele `n unit!]i lexicale$ numite atomi lexicali 0`n engle+!
ItoHensI1& ;a intrarea anali+orului lexical se prime[te programul ca un [ir amorf
de caractere$ litere spa]ii [i simboluri& ;a ie[ire re+ult! un [ir de atomi lexicali&
)radi]ional$ a[a+isele "expresiile regulate" sunt folosite pentru a defini [abloane
de recunoa[tere a atomilor de c!tre scaner 0anali+or lexical1& %cesta este
implementat ca un automat finit determinist$ o ma[in! cu un num!r de st!ri finit
care'[i sc.imb! starea la primirea cte unui caracter& 0Fot!/ 6unt posibile [i alte
te.nici$ de exemplu s'a in(entat anali+orul lexical adapti( care recuno[te [i `n(a'
]! singur diferitele categorii de atomi lexicali [i ne scute[te s! mai scriem noi
specifica]iile& )ot ce ne r!mne e s! spunem care dintre clasele de atomi
descoperite (or fi identificatori$ care numere etc& Fu (a fi `ns! subiect al acestei
c!r]i&1
;ex'ul [i Flex'ul sunt instrumentele cele mai populare de generare a anali+oarelor
lexicale $ acele programe care recunosc singure [abloane lexicale `n text& Flex este o
:
(ariant! mai rapid! a ;ex'ului$ compatibil! cu acesta la ni(el de specifica]ii& 2n acest
capitol$ prin ;ex @ Flex (om numi simultan ambele generatoare& 2n anexa despre ;ex @
Flex 0din (ersiunea engle+! a c!r]ii1 sunt preluate condensat elemente din manualul
IflexdocI scris de Vern #axon&
Analizorul sintactic 0parser'ul1 grupea+! atomii lexicali 0toHens1 `n unit!]i
0structuri1 sintactice& Ca re+ultat ob]ine o repre+entare arborescent!/ %rborele
sintactic al programului$ abre(iat ca 6) ' syntax tree$ `n literatura de limb!
engle+!& , gramatic! independent! de context furni+at! parserului 0gramatica
limba=ului1 `i spune acestuia ce structuri sintactice s! recunoasc!& #arserul este
cel mai adesea implementat ca un automat pus.'doAn& 0%dic! o ma[in! cu
num!r finit de st!ri `n+estrat! [i cu o sti(!& 3ntui]i probabil de=a c! sti(a `i este
necesar! pentru a urm!ri imbricarea structurilor sintactice$ `nc.iderea
parante+elor desc.ise `n expresii [amd&1
Bacc [i Bison sunt instrumente pentru generarea de anali+oare sintactice 0parsere '
programe care recunosc structura sintactic! a unui program1& Bison este o (ersiune mai
rapid! de Bacc& 2n acest capitol$ prin Bacc @ Bison ne (om referi la ambele instrumente&
6ec]iunea pri(ind Bacc @ Bison este o condensare [i apoi extindere a documentului
IB36,F t.e Bacc'compatible #arser 9eneratorI scris de C.arles "onell- `mpreun! cu
celebrul Dic.ard 6tallman&
Fa+a de analiz\ semantic\ prelucrea+! arborele sintactic `n c!utarea acelor
informa]ii dependente de context numite `n engle+! Istatic semanticsI 0s'ar
traduce prin Isemantic! static!I1& ;a terminarea ei se ob]ine un arbore sintactic
0%6)1 adnotat& 0"e exemplu stabilirea tipurilor (ariabilelor din expresii$ pe ba+a
declara]iilor precedente se face `n aceast! fa+!&1 Gramaticile cu atribute sunt
suportul teoretic al acestei etape& Cu a=utorul lor se descrie semantica static! a
unui program&
%ceast! fa+! se reali+ea+! de obicei concomitent cu anali+a sintactic!& 3nforma]iile
colectate `n aceast! fa+! pri(ind (ariabilele [i alte entit!]i 0definite de programator `n
program1 sunt culese [i stocate `n tabela de simboluri 0 `n engle+! ' symbol table).
%ceste informa]ii sunt folosite la (erific!rile dependente de context$ acele (erific!ri `n
care se confirm! c! o entitate a fost folosit! conform cu specifica]iile existente despre
ea&
Optimizatorul 0arborelui1 supune arborele sintactic adnotat 0%6)1 unor
transform!ri care p!strea+! sensul de ansamblu al programului dar simplific!
structura arborelui [i facilitea+! generarea unui cod mai eficient&
Generatorul de cod transform! arborele adnotat [i simplificat `n cod obiect$
folosind reguli care denot! semantica limba=ului de programare& 0Vede]i [i
materiale despre denotational semantics&1 9eneratorul de cod poate fi integrat
7
anali+orului sintactic$ astfel ca el s! genere+e cod imediat ce recunoa[te o
structur! sintactic!&
,ptimi+atorul de cod generat 0`n engle+! Ipeep'.ole optimi+er1 examinea+!
codul obiect generat [i$ constatnd uneori c! un grup de instruc]iuni ale
procesorului se poate `nlocui cu una singura sau cu un grup mai mic$ mai
eficient$ ori mai rapid$ reali+ea+! `mbun!t!]iri ale codului dependente de ma[in!&
2n contrast cu compilatorul$ interpretorul este un program care simulea+! execu]ia
programului scris `n limba=ul surs!& 3nterpretoarele pot I`n]elegeI [i executa fie direct
instruc]iuni ale unui limba= de programare de ni(el `nalt$ fie pot compila programul [i
executa iterpretati( codul re+ultat$ acest cod fiind de obicei generat ca pentru o ma[in!
(irtual!$ adic! un procesor de care nu dispunem `n form! .ardAare& 2n aceast! situa]ie$
compilatorul inclus generea+! un cod pentru acea ma[in! (irtual!$ cod care
corespunde programului ini]ial din limba=ul surs!&
<xist! o larg! palet! de translatoare care se folosesc `mpreun! cu compilatoarele `n
procesul de reali+are a programelor& >n asamblor este acel translator 0compilator dac!
(re]i1 al unui limbaj de asamblare. 3nstruc]iunile acestui limba= corespund una cte una
unei instruc]iuni din codul obiect$ adic! din limba=ul procesorului& 0Cu alte cu(inte
limba=ul de asamblare nu este un limba= structurat$ `n care s! pute]i scrie instruc]iuni
compuse$ imbricate$ ci doar cel mult expresii $ iar acestea sunt prelucrate doar de
unele asambloare mai sofisticate1& <xist! compilatoare care generea+! codul `n limba=
de asamblare iar acesta (a fi transformat `n limba= ma[in! de c!tre un asamblor& >n
`nc!rc!tor 0`n engle+! loader1 e un translator pentru care att limba=ul de la intrare c!t [i
cel de la ie[ire sunt limba= obiect& ;a intrare prime[te [i o tabel! care spune unde
trebuie modificat programul `n limba= ma[in! pentru a fi corect executat cnd este plasat
`n memorie la o adres! anume& >n link-editor e tot un fel de translator care prime[te o
colec]ie de module de program executabile [i le leag! `mpreun! formnd un singur
program executabil destinat apoi execu]iei& >n preprocesor este un translator al c!rui
limba= surs! este un fel de limba= de ni(el superior extins cu alte construc]ii$ iar al c!rui
limba= obiect este acel limba= de ni(el superior$ neextins&
Ca exemplu$ `n cele ce urmea+! (om construi un compilator pentru un limba= de
programare imperati( ' de=a clasic `n cursurile de compilatoare ' numit Simple&
9ramatica limba=ului Simple, a[a cum ne'o propune domnul %nt.on- %& %ab-$ este /
program ::= LET [ declarations ] N [command sequence] END
declarations ::= NTEGER [ id seq ] DENTFER .
id seq ::= [id seq ...] DENTFER ,
command sequence ::= command... command
10
command ::= SKP ;
| DENTFER := expression ;
| F exp THEN [command sequence] ELSE [command sequence] F ;
| WHLE exp DO [command sequence] END ;
| READ DENTFER ;
| WRTE expression ;
expression ::= NUMBER | DENTFER | '(' expression ' )'
| expression + expression | expression - expression
| expression * expression | expression / expression
| expression ^ expression
| expression = expression
| expression < expression
| expression > expression
Feterminalii sunt scri[i cu minuscule$ terminalii 0cu(intele limba=ului1 s'au scris cu
ma=uscule sau cu simboluri [i acolo unde ar fi fost pricin! de confu+ie cu metasimboluri
din <BFF$ s'au folosit [i g.ilimele simple& 6imbolul de start este program, neterminalul
corespun+!tor categoriei gramaticale a programelor complet scrise& "e[i am folosit
ma=uscule la scrierea cu(intelor limba=ului 0simbolurilor terminale1$ la implementare (om
lucra cu minuscule&
;imba=ul (a a(ea dou! reguli$ restric]ii$ dependente de context& 6e cere ca (ariabilele s!
fie declarate `nainte de a fi folosite [i ca (ariabilele s! fie declarate exact o dat!&
#entru necunosc!torii nota]iei folosite 0de inspira]ie <BFF1$ coment!m sintaxa de mai
sus$ regul! cu regul!/
program ::= LET [ declarations ] N [command sequence] END
#rogramul e format din cu(ntul obligatoriu ;<)$ ni[te declara]ii care pot lipsi 0atunci
cnd nu folosim (ariabile1$ cu(!ntul obligatoriu 3F $ sec(en]a de instruc]iuni de executat$
care poate fi [i ea (id!$ [i$ `n cele din urm! se termin! cu <F"&
declarations ::= NTEGER [ id seq ] DENTFER .
"eclara]iile `ncep cu cu(ntul 3F)<9<D [i se termin! cu un identificator 0oarecare1 [i un
punct& #oate fi dup! 3F)<9<D o sec(en]! mai lung! de al]i identificatori declara]i `n
aceea[i declara]ie&
id seq ::= [ id seq ...] DENTFER ,
%ceast! sec(en]! se termin! totdeauna cu (irgul! pus! dup! ultimul identificator [i
`ncepe cu o sec(en]! 0care not!m noi poate fi [i (id!& #ractic sec(en]a$ a[a cum (a
apare `n declara]ie$ este format! din identificatori urma]i de (irgul!$ cu excep]ia ultimului
0din declara]ie1 despre care am (!+ut din regula anterioar! c! era urmat de punct&
command sequence ::= command... command
11
6ec(en]a de comen+i este format! din comen+i puse una dup! alta$ pur [i simplu& Vom
(edea din regula urm!toare c! fiecare comand! include un simbol Ipunct [i (irgul!I&
%m scris peste tot [command sequence] cu parante+e drepte deoarece ea putea fi [i (id!$
adic! putea lipsi& 2n nota]ia de specialitate parante+a p!trat! marc.ea+! un element op'
]ional al construc]iei sintactice respecti(e&
command ::= SKP ;
| DENTFER := expression ;
| F exp THEN [command sequence] ELSE [command sequence] F ;
| WHLE exp DO [command sequence] END ;
| READ DENTFER ;
| WRTE expression ;
3nstruc]iunile posibile sunt instruc]iunea (id! 6S3#$ atribuirea$ 3F')M<F'<;6< terminat
cu F3$ TM3;<'", terminat cu <F" precum [i dou! instruc]iuni de intrare ie[ire$ absolut
necesare ca s! comunic!m cu calculatorul `n 6imple/ citirea (alorii unui identificator [i
scrierea (alorii unei expresii&
Fota]i c! 3"<F)3F3C%),D este scris cu ma=uscule ca un terminal 0iar el (a fi furni+at ca
atare dup! anali+a lexical!$ ca un singur atom lexical oricum s'ar numi el iar numele `i
(a de(eni un simplu atribut1& 2n timp ce IexpressionI $ expresia$ este scris! cu
minuscule$ ca un neterminal deoarece e numele unei categorii gramaticale din program&
<xpresiile au structur!$ nu's simboli terminali$ [i (or trebui anali+ate sintactic mai
departe& Felul cum sunt structurate expresiile e descris de regula urm!toare/
expression ::= NUMBER | DENTFER | '(' expression ' )'
| expression + expression | expression - expression
| expression * expression | expression / expression
| expression ^ expression
| expression = expression
| expression < expression
| expression > expression
<xpresia poate fi un simplu num!r$ un simplu identificator sau o expresie pus! `n
parante+! 0ce se comport! ca (aloarea ei1& *ai poate fi o sum!$ o diferen]!$ un produs
sau un ct de expresii precum [i un Kade(!ratJ 011 sau KfalsJ 001 re+ultat `n urma unei
compara]ii$ a unei (erific!ri dac! alte dou! expresii sunt `ntr'o rela]ie de egalitate $
inegalitate ori compara]ie de un fel sau altul 0 U $ V 1&
,bser(a]ie/ acele categorii gramaticale care corespund unor neterminali din care poate
deri(a un [ir (id 0deci acelea care pot lipsi1 au fost$ nu uita]i$ puse `n parante+!& Vom
(edea `n capitolul urm!tor o alt! nota]ie pentru gramatica limba=ului 6imple$ e(iden]iind
ni[te reguli 0sau mai corect alternati(e ale unor reguli1 cu partea dreapt! (id!& "ar
aceasta la momentul potri(it& "eocamdat!$ `n acest capitol$ am (rut doar s! (a
familiari+!m cu limba=ul ce urmea+! a fi implementat&
12
Capitolul 2
%nali+orul sintactic 0#arser'ul1
>n parser este un program care determin! dac! textul primit de el este sintactic corect
[i `n plus$ `i determin! c.iar structura& %ltfel spus nu spune doar ICorect RI sau I3ncorect
RI& #arserele pot fi scrise de mn! sau pot fi automat generate de un generator de
anali+oare sintactice$ pornind de la descrierea unor structuri sintactice corecte 0ce (or fi
recunoscute$ (alidate$ de (iitorul parser1& %ceste descrierei de sintax! iau forma unor
gramatici independente de context& 9eneratoarele de anali+oare sintactice pot fi
folosite la de+(oltarea de parsere pentru o gam! larg! de limba=e$ de la limba=ul
expresiilor cu parante+e pe care `l folose[te un calculator de birou pn! la cele mai
complexe limba=e de programare&
Bacc @ Bison este un asemenea generator care primind la intrare o descriere a unei
gramatici independente de context 093C1 construie[te un program `n C 0iar (ersiunile
noi de Bison pot produce [i programe `n CPP RR1 care (a anali+a sintactic un text
conform cu regulile gramaticii date& Bacc a fost de+(oltat de 6& C& Wo.nson [i de colegii
s!i de la %)X) Bell ;aboratories& %tt Bacc ct [i Bison permit s! manipula]i `mpreun!
cu sti(a anali+orului sintactic o a doua sti(! 0`n care se operea+! sincron cu prima la
fiecare `ncepere@terminare de structur! sintactic!1$ aceast! a doua sti(! fiind destinat!
manipul!rilor f!cute de rutinele semantice& 0Fu uita]i c! (om face traducere Is-ntax'
dri(enI$ deci condus! de sintax!1&
Fi[ierul de intrare pentru Bacc@Bison are urm!toarea structur!/
declara]ii C [i declara]ii parser
%%
Degulile gramaticii [i ac]iunile semantice ata[ate 0care (or opera cu a doua sti(!1
%%
Func]ii C 0adesea aici se include [i func]ia *ain$ care nu e generat! automat1
#e scurt/
declara]ii C [i parser
%%
Deguli
%%
Func]ii C
#rima sec]iune con]ine [i lista atomilor lexicali 0diferi]i de simple caractere1 care sunt a
[tepta]i de c!tre parser deoarece fac parte din limba=& )ot aici se include [i declara]ia
simbolului ini]ial din gramatic!$ acel neterminal care corespunde no]iunii de program
complet& %ceast! sec]iune poate con]ine [i specifica]ii pri(ind ordinea opera]iilor [i
asociativitatea operatorilor. Ca efect$ utili+atorul are o mai mare libertate `n proiectarea
limba=ului$ `n algerea gramaticii sale& %dunarea [i sc!derea (or fi declarate asociati(e la
stnga [i cu cea mai mic! preceden]! `n timp ce ridicarea la putere este declarat! ca
15
fiind asociati(! la dreapta [i a(nd cea mai mare preceden]!$ cea mai mare prioritate&
%start program
%token LET NTEGER N
%token SKP F THEN ELSE END WHLE DO READ WRTE F
%token NUMBER
%token DENTFER ASSGNOP
%left '-' '+'
%left '*' '/'
%right '^'
%%
Reguli ale gramaticii cu ac]iuni
%%
Subrutine C
% doua sec]iune a fi[ierului cuprinde gramatica independent! de context a limba=ului de
anali+at& Degulile 0numite produc]ii1 sunt aici separate prin IYI 0punct [i (irgul!1$ simbolul
Z ::= Z este `nlocuit de Z/Z $ o e(entual! parte dreapt! (id! este scris! ca atare $
neterminalii sunt scri[i cu minuscule iar terminalii din mai multe simboluri 0cum este
semnul atribuirii1 cu ma=uscule& Demarca]i o anumit! simplificare a gramaticii datorit!
separ!rii informa]iilor despre prioritatea operatorilor de restul gramaticii& 0Constructorii
de compilatoare cu experien]! [tiu c! lund `n considerare prioritatea operatorilor$
gramatica expresiilor aritmetice se scrie cu mai multe reguli dect `n exemplul nostru&1
Declaratiile anterioare
%%
program : LET declarations N commands END ;
declarations : /* empty */
| NTEGER id seq DENTFER '.'
;
id seq : /* empty */
| id seq DENTFER ','
;
commands : /* empty */
| commands command ';'
;
command : SKP
| READ DENTFER
| WRTE exp
| DENTFER ASSGNOP exp
| F exp THEN commands ELSE commands F
| WHLE exp DO commands END
;
exp : NUMBER
| DENTFER
| exp '<' exp
| exp '=' exp
| exp '>' exp
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
14
| exp '^' exp
| '(' exp ')'
;
%%
Subrutine C
% treia sec]iune din fi[ierul cu specifica]ii Bacc const! `ntr'o colec]ie de func]ii scrise `n
limba=ul C& #rintre ele se recomand! s! existe func]ia main() care (a apela func]ia
yyparse(). Func]ia yyparse() este de fapt subrutina produs! de generator 0pe ba+a
specifica]iilor de mai `nainte1 [i este cea care (a conduce anali+a sintactic!& 2n ca+ de
eroare ea (a `ncerca s! apele+e func]ia yyerror() pentru a semnala [i prelucra
eroarea& %ceast! func]ie --parse01 e l!sat! s! fie scris! de programator$ ceea ce
confer! flexibilitate& 3at! ni[te exemple simple cum ar putea ar!ta func]iile main01 [i
--parse01/
declara]ii C [i declara]ii parser
%%
Degulile gramaticii
%%
main( int argc, char *argv[] )
{ extern FLE *yyin;
++argv; --argc;
yyin = fopen( argv[0], 'r' );
yydebug = 1;
/* errors = 0; */
yyparse ();
}
yyerror (char *s) /* Called by yyparse on error */
{ /* errors ++; */
printf ("%s\n", s);
}
Fot!/ Variabila errors (a num!ra erorile din timpul anali+ei sintactice& #ute]i renun]a la
ea dac! nu dori]i acest lucru& "ac! totu[i dori]i s'o folosi]i$ elimina]i comentariile de pe
rndurile unde se fac referin]e la ea [i nu uita]i s'o declara]i ca (ariabil! global! a
programului `n sec]iunea declara]iilor C& 0 int errors; 1
"ar pentru a nu complica acest exemplu minimal ('a[ recomanda ca `n prima fa+! s!
renun]a]i la ea&
#arserul$ a[a cum este generat pe ba+a specifica]iilor de pn! acum$ nu generea+!
nimic la ie[ire$ nici m!car arborele sintactic& %cesta este `ns! implicit construit `n timpul
anali+ei& #e m!sur! ce anali+a progresea+!$ parserul crea+! ni[te structuri interne care
corespund sintaxei programului anali+at& Depre+entarea aceasta intern! se ba+ea+! pe
p!r]ile drepte ale regulilor gramaticii& Cnd o parte dreapt! a unei produc]ii 0reguli1 este
recunoscut! ea e `nlocuit! cu partea stng! corespun+!toare& ,pera]ia se nume[te
reducere. Vom spune c! partea dreapt! a regulii a fost redus\ la neterminalul din
15
stnga regulii& %cesta la rndul s!u este candidat la a figura `n partea dreapt! a unei
alte reguli [i a[a mai departe pn! cnd `ntregul program este redus la simbolul de start
al gramaticii$ semn c! anali+a a reu[it cu succes&
Compilarea fi[ierului surs! de mai sus$ simple.y se face cu Bacc$ tastnd comanda/
-acc '(d simple&-
sau pe un sistem ;inux pe care este instalat Bison$ cu comanda/
bison '(d simple&-
sau
bison 'd( simple&-
&&&unde pute]i `nlocui pe simple&- cu numele fi[ierului dumnea(oastr!&
2n urma prelucr!rii se ob]ine un fi[ier cu extensia dubl! &tab&c [i acela[i nume `naintea
extensiei ca fi[ierul ini]ial& 2n exemplul nostru se (a numi simple&tab&c deoarece
specifica]iile se numeau simple&- & <xtensia tradi]ional! a fi[ierelor cu specifica]ii
Bacc@Bison este &- &
Fi[ierul &tab&c astfel ob]inut poate fi compilat cu compilatorul de C de pe sistemul
dumnea(oastr! >nix @ ;inux& <l con]ine [i func]iile scrise de dumnea(oastr! [i func]ia
generat! --parse01 care face anali+a& 6istemul de ,perare ;inux (ine cu compilatorul
9CC$ iar linia de comand! necesar! pentru a compila sursa &c (a fi/
gcc 'c simple&tab&c
&&& ceea ce duce la ob]inerea modulului obiect cu numele simple&tab&o &
Fota]i [i faptul c! `n urma folosirii Bacc @ Bison se mai generea+! un fi[ier$ cu extensia &
tab&. & %cesta con]ine defini]ii de constante care asigur! transferul corect al informa]iilor
`ntre anali+orul sintactic 0parserul1 generat de Bacc @Bison [i anali+orul lexical generat
de Flex @ ;ex & 3deea este c! fiecare tip de atom lexical (a a(ea un num!r$ iar aceste
numere definite [i a[teptate de parserul produs de Bacc @ Bison trebui s!'i (in! de la
anali+orul lexical& %cesta trebuie deci [i el s! le cunoasc!$ ceea ce (a face inclu+nd `n
sursa sa fi[ierul cu extensia &tab&. generat de Bacc @ Bison&
Fu c!uta]i Bacc pe sistemele ;inux& Bacc este distribuit `mpreun! cu sistemele >nix&
6istemele ;inux$ oferite sub licen]a 9F> 9#; de c!tre Free 6oftAare Foundation 3nc&$
au `n distribu]ie Bison `n loc de Bacc& Bison este un produs al Free 6oftAare
Foundation&
#entru mai multe informa]ii despre folosirea Bacc @ Bison (! rug!m fie s! c!uta]i `n
anexele c!r]ii de fa]!$ fie s! consulta]i pagina de manual pentru bison folosind
comanda/
man bison
18
*ai pute]i citi 0dac! le g!si]i R1 lucr!rile/ I#rogramming >tilities and ;ibraries ;D #arsingI
de %&V&%.o [i 6&C&Wo.nson publicat! `n Computing 6ur(e-s `n iunie 1744 [i documentul
IB36,F t.e Bacc'compatible #arser 9eneratorI$ de C.arles "onnell- [i Dic.ard
6tallman&
2n urma complet!rii tuturor celor trei sec]iuni ale fi[ierului Bacc$ acesta (a ar!ta ca mai
=os/
/* Declaratii */
%start program
%token LET NTEGER N
%token SKP F THEN ELSE END WHLE DO READ WRTE F
%token NUMBER
%token DENTFER ASSGNOP
%left '-' '+'
%left '*' '/'
%right '^'
%%
program : LET declarations N commands END ;
declarations : /* empty */
| NTEGER id_seq DENTFER '.'
;
id_seq : /* empty */
| id_seq DENTFER ','
commands : /* empty */
| commands command ';'
;
command : SKP
| READ DENTFER
| WRTE exp
| DENTFER ASSGNOP exp
| F exp THEN commands ELSE commands F
| WHLE exp DO commands END
;
exp : NUMBER
| DENTFER
| exp '<' exp
| exp '=' exp
| exp '>' exp
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| exp '^' exp
| '(' exp ')'
;
%%
/* Subrutine */
int main (int argc, char * argv[] )
{extern FLE *yyin;
++argv; --argc;
14
yyin = fopen( argv[0], "r" );
yydebug = 1 ;
yyparse();
}
yyerror (char *s) /* Called by yyparse on error */
{
print("%s\n", s);
}

#entru a'l procesa urma]i indica]iile din paginile precedente sau exemplul de sesiune
de lucru la terminal dat `n anex!&
1:
Capitolul 5
6caner'ul 0%nali+orul lexical1
>n anali+or lexical 0engl& scanner1 este un program capabil s! descopere [i s! clasifice
por]iuni de text 0Icu(inteI1 conforme cu ni[te [abloane date& %nali+oarele lexicale pot fi
ori scrise de mn!$ ori generate automat de un generator de anali+oare lexicale$ pe
ba+a listei de [abloane pe care le au de recunoscut& "escrierea acestor [abloane se
face sub form! de expresii regulate&
;ex este un generator de anali+oare lexicale de+(oltat de *&<&;esH [i <&6c.midt de la
%)X) Bell ;aboratories& ;ex prime[te la intrare un fi[ier con]innd descrierile atomilor
de recunoscut$ fiecare clas! de asemenea atomi 0ex& numere$ identificatori etc1 fiind
caracteri+at!$ descris!$ de o expresie regulat!& ;ex produce la ie[ire un `ntreg modul de
program$ scris `n C$ care poate fi compilat [i linH'editat `mpreun! cu alte module&
0#rintre aceste module este adesea [i cel generat de Bacc @Bison ' anali+orul sintactic '
precum [i alte componente ale unui compilator$ sau interpretor&1 Fi[ierul de intrare
pentru ;ex @Flex este organi+at similar cu cel pentru Bacc @Bison $ tot `n trei sec]iuni
separate prin LL& #rima con]ine declara]ii pentru scanner [i alte declara]ii C $ a doua
con]ine `n loc de gramatic! descrierile atomilor lexicali 0toHens1 sub form! de expresii
regulate [i ac]iunile pe care le (a face anali+orul `ntlnindu'le 0de obicei returnea+!
parser'ului codul atomului respecti($ e(entual [i alte informa]ii1 iar a treia con]ine restul
de subrutine 0func]ii1 scrise `n C&
Ca urmare a prelucr!rii intr!rii$ ;ex produce un fi[ier cu extensia &c$ `n care e definit!
func]ia yylex(), func]ie ce (a returna un `ntreg corespun+!tor fiec!rui atom g!sit&
%ceast! func]ie (a fi apelat! de func]ia main() scris! de programator `n ultima sec]iune$
dac! facem doar recunoa[terea [i prelucrarea atomilor lexicali sau de func]ia din
modulul de anali+! sintactic!$ dac! construim un compilator sau un interpretor& 2ntr'o
asemenea situa]ie func]ia --lex01 ofer! ser(icii 0(alori1 func]iei --parse01 din modulul
generat de Bacc@Bison&
Codurile di(ersilor atomi lexicali sunt la fel `n]elese de ambele func]ii --lex01 [i --parse01
deoarece fi[ierul generat de ;ex (a cuprinde [i directi(a de includere a fi[ierului .eader
generat de Bacc$ cu extensia &tab&.& 3ncluderea pic! `n sarcina programatorului&
%[a arat! fi[ierul de intrare pentru ;ex/
declara]ii C [i declara]ii pentru scanner
%%
"escrieri de atomi lexicali sub forma expresilor regulate [i ac]iuni
%%
Func]ii C $ subrutine
17
2n exemplul nostru$ cea dinti declara]ie care se (a scrie `n prima sec]iune a fi[ierului
pentru ;ex este cea de includere a fi[ierului simple&tab&.& $ generat anterior de Bacc @
Bison& <l con]ine defin]ii pri(ind atomii multi'caracter& "e asemenea$ prima sec]iune
cuprinde o serie de defini]ii a=ut!toare pentru scrierea expresiilor regulate din sec]iunea
a doua& 2n exemplul nostru (om defini aici pe "393) ca o sec(en]! de una sau mai
multe cifre de la 0 la 7 iar pe 3" 0de la identificator1 ca fiind o liter! urmat! de una sau
mai multe litere [i@sau cifre&
%{
#include "simple.tab.h" /* The tokens */
%}
DGT [0-9]
D [a-z][a-z0-9]*
%%
"escrieri de atomi lexicali sub forma expresilor regulate [i ac]iuni
%%
Func]ii C $ subrutine
#or]iunea dintre %{ [i %} (a fi transcris! f!r! modific!ri `n textul generat& ,bser(a]i c!
am folosit directi(a #include pentru a include fi[ierul simple&tab&. & 0'7 semnific! o cifr!
din mul]imea de cifre de la 0 la 7& a'+ `nseamn! o liter! din mul]imea de litere de la a la
+ iar a'+0'7 un simbol din reuniunea celor dou! mul]imi& ,bser(a]i c! se scriu cu
parante+! p!trat! nu cu acolad!& 6telu]a de dup! parante+a p!trat! `nseamn! c! pot fi
oricte elemente din acea mul]ime `n succesiune imediat!$ inclusi( nici unul& 2n cele din
urm! facem obser(a]ia c! "393) repre+int! orice cifr! iar 3" orice identificator&
% doua sec]iune din fi[ierul ;ex 0acestea au extensia &lex1 este seria de pereci [ablon
0dat de expresia regulat!1 - ac]iune 0dat! ca un corp de func]ie C$ cuprins `n acolade1&
Fiec!rui fel de atom lexical 0toHen1 descoperit `i corespunde o ac]iune bine preci+at!&
Qirurile de unu sau mai mul]i digi]i sunt recunoascute ca numere `ntregi [i ca urmare$
(aloarea constantei F>*B<D (a fi returnat! parserului& Cu(intele re+er(ate ale
limba=ului sunt sec(en]e de litere minuscule& 06e poate lucra [i cu ma=uscule dar ele (a
fi necesar s! fie tratate altfel RR1 6pa]iile albe$ blanc'uri$ tab'uri (or fi ignorate$ nu (or
produce nici o ac]iune& 2n dreptul lor `n loc de ac]iune este un comentariu& )oate
celelalte caractere 0ceea ce `n ;ex se notea+! cu simbolul punct K.J1 (or fi pur [i simplu
returnate a[a cum sunt& 6canerul plasea+! textul de parcurs `n (ariabila string yytext [i
`ntotdeauna yytext[0] este caracterul curent de prelucrat&
declara]ii C [i declara]ii pentru scanner
%%
":=" { return(ASSGNOP); }
{DGT}+ { return(NUMBER); }
do { return(DO); }
else { return(ELSE); }
end { return(END); }
fi { return(F); }
if { return(F); }
in { return(N); }
20
integer { return(NTEGER); }
let { return(LET); }
read { return(READ); }
skip { return(SKP); }
then { return(THEN); }
while { return(WHLE); }
write { return(WRTE); }
{D} { return(DENTFER); }
[ \t\n]+ /* blank, tab, new line: eat up whitespace */
. { return(yytext[0]); }
%%
Subrutine C
,bser(a]i c! fiec!rui tip de atom lexical i se asocia+! de regul! ac]iunea de a `ntoarce o
(aloare `ntreag! 0constant!1 care semnific! felul de atom lexical descoperit&
;ista urm!toare cuprinde forma ctor(a feluri u+uale de expresii regulate care (! pot fi
de folos la a specifica atomii lexicali de recunoscut& Fota]i [i faptul c! exist! o (ariabil!
global! yylval , accesibil! att scanerului generat de ;ex ct [i parserului generat de
Bacc @Bison& <a poate fi folosit! pentru a transmite alte informa]ii legate de atomul al
c!rui cod tocmai a fost returnat&
. orice caracter cu excep]ia returului de car$ <F)<D
x [ablonul care se potri(e[te cu caracterul ZxZ
rs concatenarea 0succesiunea1 a ce(a care se potri(e[te cu r [i ce(a ce se potri(e[te cu s
r|s reuniunea sau alternati(aY se potri(esc cu ea at`t sec(en]ele de cractere corespun+!toare
expresiei r c`t [i cele corespun+!toare expresiei s
(r) la fel ca r ; parentezele se folosesc la grupare
r* +ero sau mai multe sec(en]e de caractere ce se potri(ese cu r$
unde r poate fi orice expresie regulat!
r+ una sau mai multe sec(en]e de caractere ce se potri(ese cu r$
unde r poate fi orice expresie regulat!
[xyz] o clas! 0mul]ime1 de caractere$ `n acest exemplu se (or potri(i cu [ablonul doar caracterele
ZxZ $ Z-Z$ Z+Z
[abj-oZ] o clas! 0mul]ime1 de caractere$ `n acest exemplu se (or potri(i cu [ablonul doar
caracterele ZaZ sau ZbZ $orice de la Z=Z la ZoZ inclusi($ sau Z[Z
{NAME} expandarea unei 0macro1defini]ii anterioare$ cu numele F%*<
\X dac! N este un ul dintre caracterele ZaZ$ ZbZ$ ZfZ$ ZnZ$ ZrZ$ ZtZ sau Z(Z $ atunci \X se interpretea+!
conform standardului ANS-C
"[+xyz]+\"+foo" stringul: [xyz]"foo
21
% treia sec]iune a fi[ierului (a fi l!sat! necompletat! `n acest exemplu& "ar `n ca+ul `n
care ac]iunile anali+orului lexical presupuneau opera]ii complexe [i apeluri de func]ii
utili+ator$ aceste func]ii puteau fi ad!ugate aici$ `n a treia sec]iune& %stfel scrierea ac]i'
unilor de(ine mai clar! iar unele detalii nesemnificati(e sunt ascunse `n func]iile
0subrutinele1 din a treia sec]iune&
Compilarea fi[ierului ;ex se face cu una din comen+ile/
lex !i"ier.lex
respecti(
flex !i"ier.lex
[i se (a ob]ine un fi[ier cu denumirea lex&--&c `n care e generat! func]ia yylex(). ;a
fiecare apel al func]iei --lex01$ intrarea (a fi scanat! 0parcurs!1 `n c!utarea urm!torului
atom lexical [i se (a executa ac]iunea programat! care'i corespunde& 2n ca+ul din
exemplul nostru se (a returna codul atomului respecti(&
Ve]i lucra cu ;ex dac! a(e]i un sistem >nix de firm!$ deoarece ;ex este distribuit
`mpreun! cu sistemele >nix sau cu IclonaI acestuia$ Flex$ dac! folosi]i un sistem ;inux&
Flex este un produs al Free 6oftAare Foundation$ 3nc&$ distribuit sub licen]! gneral!
public! 9F> 9#;&
, sesiune tipic! de lucru cu o ma[in! ;inux$ folosind Flex$ Bison [i compilatorul 9CC
pentru a ob]ine programul binar$ executabil$ 0in sursele C nerate de Flex [i Bison1 se
desf![oar! d!nd comen+ile din lista de mai =os& %m presupus c! cele dou! fi[iere cu
specifica]ii se numesc simple.y [i simple.lex& #romptul sistemului este notat cu I\I de
obicei [i nu face parte din comand!/
\ bison 'd( simple.y
\ gcc 'c simple.tab.c
\ flex simple.lex
\ gcc 'c lex&--&c
\ gcc 'o simple simple.tab.o lex&--&o 'lm 'lfl
#rima comand! in(oc! Bison pentru a genera din sursa simple.y fi[ierul simple.tab.c [i
fi[ierul simple.tab. care figurea+! ca inclus `n sursa ce V% F3 generat! de Flex @;ex&
% doua in(oc! compilatorul gcc pentru a compila simple.tab.c [i a ob]ine modulul obiect
simple.tab.o.
% treia generea+! din specifica]ia ;ex simple.lex sursa C cu nume standard lex&--&c&
% patra este comanda de compilare a acestei surse [i re+ult! modulul obiect lex&--&o&
2n sfr[it$ cu ultima comand! se leag! modulele obiect simple.tab.o [i lex&--&o `mpreun!
cu o serie de func]ii de bibliotec! `n executabilul binar simple& %ten]ie la op]iunile din
finalul liniei de comand!& #e sistemul Ded Mat ;inux 5&2 cu care am rulat prima oar!
aceste exemple trebuie scrise neaparat op]iunile ';* ';F; dar cu minuscule RRR #e alte
(ersiuni de sisteme ;inux este suficient! doar prima op]iune ';* scris! tot cu
minusculeR
22
#entru mai multe informa]ii despre comen+ile [i op]iunile ;ex @ Flex consulta]i paginile
de manual lex $ flex de pe sistemul dumnea(oastr! >nix @ ;inux$ documenta]ia flexdoc
[i citi]i lucrarea I;ex ' ;exical %nal-+er 9enerator de *& <& ;esH [i <& 6c.midt$ `n ca+ul
cnd o pute]i g!si&
2n final$ `ntregul fi[ier simple&lex$ pentru limba=ul 6imple$ arat! a[a/
%{
#include "simple.tab.h" /* The tokens */
%}
DGT [0-9]
D [a-z][a-z0-9]*
%%
":=" { return(ASSGNOP); }
{DGT}+ { return(NUMBER); }
do { return(DO); }
else { return(ELSE); }
end { return(END); }
fi { return(F); }
if { return(F); }
in { return(N); }
integer { return(NTEGER); }
let { return(LET); }
read { return(READ); }
skip { return(SKP); }
then { return(THEN); }
while { return(WHLE); }
write { return(WRTE); }
{D} { return(DENTFER); }
[ \n\t]+ /* blank, tab, new line: eat up whitespace */
. { return(yytext[0]); }
%%
Comentariile le pute]i scrie$ bine`n]eles [i `n limba romn!& #rimul ! "#e to$ens ! s'ar
putea traduce prin !%tomii lexicali! de[i textual toHens `nseamn! K=etoaneleJ&
%l doilea @] blanH$ tab$ neA line/ eat up A.itespace ]@ s'ar traduce mai bine prin
! succesiunile formate cu spa]iu, tab sau enter & toate sunt consumate !.
25
24
Capitolul 4
Contextul
6pecifica]iile din fi[ierele ;ex [i Bacc potr fi extinse pentru a manipula informa]ii
dependente de context& "e exemplu$ s! presupunem c! `n limba=ul 6imple impunem ca
(ariabilele s! fie declarate `nainte de a fi folosite& "in acest moti( parserul 0anali+orul
sintactic1 trebuie s! fie capabil s! compare referin]ele la (ariabile cu declara]iile
acestea$ care sunt memorate `n (ederea (erific!rilor&
>n mod de a re+ol(a aceast! problem! este de a construi `nc! din timpul parcurgerii
sec]iunii de declara]ii a programului un fel de list! de (ariabile [i de a (erifica apoi
fiecare (ariabil! `ntlnit!$ comparnd'o cu datele de pe list!& , asemenea list! este
numit! tabel\ de simboluri& )abelele de simboluri pot fi implementate folosind liste$
arbori$ 0arbori de c!utare1 sau tabele'.as.&
Vom modifica fi[ierul ;ex pentru a atribui (ariabilei globale yylval un string cu informa]ii
de identificare de fiecare dat! cnd `ntlnim o entitate 0atom1 a c!rei set de
caracteristici se (or p!stra `n context& %semenea informa]ii (or fi$ `n teorie$ atribute
prelucrate de gramatica cu atributre&
*odulul )abel! de 6imboluri 06)&.1
#entru a p!stra informa]iile cerute de prelucr!rile ce le (a face gramatica cu atribute$
(om construi o tabel! de simboluri& )abela de simboluri cuprinde informa]ii de context
pri(ind atributele di(erselor construc]ii 0sintactice1 scrise `n limba=ul de programare&2n
particular$ pentru (ariabile$ cuprinde informa]ii despre tipul 0eng& type 1 [i domeniul de
(i+ibilitate 0eng& scope 1 al (ariabilei&
)abela de simboluri pe care o (om de+(olta (a fi un modul surs! C care se (a include
de c!tre sursa generat! 0de c!tre Bacc @ Bison 1$ cu oca+ia compil!rii&
Cititorul ambi]ios este in(itat ca$ dup! parcurgerea integral! a acestui (olum$ s!
in(ente+e un limba= de specificare a tabelelor de simboluri [i un generator de surse C
0similar Bacc'ului [i Bison'ului1 pentru a genera module asem!n!toare celui de mai =os
pornind de la specifica]ii& 3nstrumentele cu care (a lucra (or fi e(ident Bacc @ Bison
pentru anali+a sintactic! [i generarea outputului prin ac]iuni semantice [i ;ex @Flex
pentru anali+a lexical!1&
)abela de simboluri pentru limba=ul 6imple const! `ntr'o list! simplu `nl!n]uit! de
identificatori$ ini]ial (id!& 3at! declara]ia unui nod 0element1 al listei
struct symrec
{char *name; /* name of symbol - numele simbolului*/
25
struct symrec *next; /* link field - pointerul la alt element*/
};
apoi definirea tipului symrec [i ini]iali+area listei (ide cu un pointer nul
typedef struct symrec symrec;
symrec *sym_table = (symrec *)0;
symrec *putsym ();
symrec *getsym ();
[i cele dou! opera]ii& #rima$ putsym e cea care pune un identificator `n tabel!
symrec *
putsym ( char *sym_name )
{symrec *ptr;
ptr = (symrec *) malloc (sizeof(symrec));
ptr -> name = (char *) malloc (strlen(sym_name)+1);
strcpy (ptr -> name, sym_name);
ptr -> next = (struct symrec *)sym_table;
sym_table = ptr;
return ptr;
}
Comente+ pu]in codul func]iei putsym pentru e(entualii cititori mai pu]in familiari+a]i cu
limba=ul C& "ac! st!pni]i bine C'ul$ trece]i direct la pagina urm!toare$ la func]ia getsym&
#rimul rnd declar! tipul re+ultatului dat de func]ie$ care e pointer la un record 0element
de list!1 symrec$ deci e [i pointer la o list! de asemenea elemente&
symrec *
>rmea+! numele func]iei [i parante+a cu parametrul formal unic de tip pointer la
caracter 0sinonim `n C cu string1$ cu numele sym#name/
putsym ( char *sym_name )
Corpul func]iei `ncepe cu declararea (ariabilei locale ptr$ pointer la tipul symrec/
{symrec *ptr;
6e aloc! spa]iu pentru structura 0record'ul1 propriu'+is [i pentru numele sym#name ce e
destinat a fi stocat `n acea intrare din tabel!&
ptr = (symrec *) malloc (sizeof(symrec));
ptr -> name = (char *) malloc (strlen(sym_name)+1);
6e copie apoi numele dat ca parametru `n spa]iul alocat de=a$ indicat de pointerul
ptr-$name$ stocnd astfel copia numelui `n tabel!& 0Func]ia C strcp-01 este o (eritabil!
atribuire pentru stringuri$ capabil! s! copie al doilea string de la adresa sa$ la adresa
primului string$ dat! ca prim parametru&1
28
strcpy (ptr -> name, sym_name);
<lementul nou creat$ aflat la adresa ptr de(ine primul element din list! iar capul de list!
sym#table (a arata acum spre el& )ot aceast! adres! a elementului nou [i simultan a
listei este returnat! de func]ia al c!rei corp se `nc.eie cu obi[nuita acolad!&
ptr -> next = (struct symrec *)sym_table;
sym_table = ptr;
return ptr;
}
3ar getsym returnea+! un pointer c!tre intrarea din tabela de simboluri corespun+nd
unui identificator dat sau pointerul nul$ +ero$ dac! nu l'a g!sit&
symrec *
getsym ( char *sym_name )
{symrec *ptr;
for (ptr = sym_table ; ptr != (symrec *) 0 ; ptr = (symrec *)ptr- >next)
if (strcmp (ptr ->name,sym name) == 0)
return ptr;
return 0 ; /* sau eventual return (symrec *) 0; */
}
2n final$ modulul 6)&. ar putea ar!ta a[a/
/* ST.h the symbol table module */
/* De Dan Popa, dupa Anthony A Aaby , "Compiler Construction using Flex and Bison" */
/* Cap 4 pg 14 */
struct symrec
{
char *name; /* name of symbol - numele variabilei*/
struct symrec *next; /* link field - legatura la elementul urmator */
};
typedef struct symrec symrec;
symrec *sym_table = (symrec *)0;
symrec *putsym ();
symrec *getsym ();
/* Doua operatii: punerea unui identificator in tabela ...*/
symrec *
putsym ( char *sym_name )
{
symrec *ptr;
ptr = (symrec *) malloc (sizeof(symrec));
24
ptr->name = (char *) malloc (strlen(sym_name)+1);
strcpy(ptr->name, sym_name);
ptr->next = (struct symrec *) sym_table;
sym_table = ptr;
return ptr;
}
/* si a doua operatie: aflarea pointerul intrarii din tabel corespunzator unui identificator. */
symrec*
getsym (char *sym_name)
{
symrec *ptr;
for (ptr = sym_table; ptr != (symrec *)0; ptr = (symrec *) ptr->next)
if (strcmp (ptr->name, sym_name) == 0 )
return ptr;
return 0;
}
,bser(a]iu c! func]ia caut! `n lista sym#table parcurgnd'o cu pointerul 0local1 ptr ct!
(reme mai sunt elemente `n list! deci pointerul e nenul& "ac! stringul dat sym#name
coincide cu string'ul din elementul de list! curent$ adresa acestuia este returnat!& %ltfel
se returnea+! un 0 0care e practic un pointer nul1& Func]ia strcmp%& compar! stringurile
de la cele dou! adrese&

*odific!rile anali+orului sintactic 0parserului1
<ste necesar s! modific!m specifica]iile oferite Bacc'ului @ Bison'ului$ astfel `nct s!
includem tabela de simboluri [i rutinele necesare introducerii [i c!ut!rii unui identificator
`n (ederea (erific!rii folosirii sale corecte$ conforme contextului& %m ad!ugat [i (ariabila
pentru num!rarea erorilor$ errors$ nedeclarat! `n capitolul anterior& %d!ugirile se fac `n
sec]iunea de specifica]ii pe care Bacc @ Bison le (a copia direct `n sursa C generat!$
adic! (or fi scrise la `nceput$ `ntre %{ [i %}.
%{
#include <stdlib.h> /* nclude malloc, necesar pt. symbol table */
#include <string.h> /* nclude strcmp, necesar pt. symbol table */
#include <stdio.h> /* Functii pentru afisarea de mesaje de eroare */
#include "ST.h" /* Modulul "Symbol Table" */
#define YYDEBUG 1 /* Pentru debugging setez variabila Yacc la valoarea 1*/
int errors; /* Contor de erori */
install ( char *sym_name )
{ symrec *s;
s = getsym (sym_name);
if (s == 0)
s = putsym (sym_name);
else { errors++;
printf( "%s is already defined\n", sym_name );
2:
}
}
context check( char *sym_name )
{ if ( getsym( sym_name ) == 0 )
printf( "%s is an undeclared identifier\n", sym_name );
}
%}
Declaratii pentru Parser
%%
Gramatica: reguli plus actiuni
%%
Subrutine C
"eoarece anali+orul lexical 0scanerul generat de ;ex @ Flex1 (a returna doar (alorile
unor identificatori 0constante `ntregi1 [i doar att$ o structur! de record semantic
0semantic! static!1 este necesar! pentru a transmite denumirea fiec!rui identificator de
(ariabil!& %[a putem deosebi (ariabilele `ntlnite deoarece altfel anali+orul lexical
returnea+! doar o aceea[i (aloare a constantei 3"<F)3F3<D pentru orice (ariabil!&
6imple&lex (a fi modificat astfel/
Declaratii C
%union { /* RECORD SEMANTC */
char *id; /* Pentru transferul numelor identificatorilor*/
}
%start program
%token NT SKP F THEN ELSE F WHLE DO END
%token <id> DENTFER /* Simple identifier */
%left '-' '+'
%left '*' '/'
%right '^'
%%
Gramatica: reguli plus actiuni
%%
Subrutine C
2n continuare$ gramatica independent! de context [i ac]iunile ei semantice sunt
modificate pentru a include apeluri la func]iile install%& [i context#ceck%& . Fota]i c!
fiecare \n este o (ariabil! Bacc care face referire la al n'lea record semantic$ cel
corespun+!tor celui de'al n'lea element din partea dreapt! a unei produc]ii 0reguli a
gramaticii1& %stfel (om putea prelucra$ stoca$ testa$ denumirile di(er[ilor identificatori de
(ariabile care apar `n regulile gramaticii$ `n di(erse po+i]ii 0date de ordinea sintactic!1&
*etoda se aplic! la orice fel de element sintactic 0nu numai identificator de (ariabil!1 a
c!rui propriet!]i$ atribute$ urmea+! s! le prelucr!m& Demarca]i c! po+i]ia cu(ntului
3"<F)3F3<D `n regula gramaticii corespunde ca num!r cu (ariabila \n implicat! `n ac]i'
unea semantic!$ 0unde n este acela[i num!r R 1&
Declaratiii pt. C si parser
%%
...
27
declarations : /* empty */
| NTEGER id_seq DENTFER '.' { install( $3 ); }
;
id_seq : /* empty */
| id_seq DENTFER ',' { install( $2 ); }
;
command : SKP
| READ DENTFER { context_check( $2 ); }
| DENTFER ASSGNOP exp { context_check( $1 ); }
...
exp : NT
| DENTFER { context_check( $2 ); } ...
%%
Subrutine C
"up! modificare [i sal(area fi[ierului cu numele simple.y$ Bison 0pe un sistem ;inux1 (a
fi in(ocat cu una din comen+ile/
bison '(d simple.y
bison 'd simple.y
2n aceast! implementare arborele sintactic este creat implicit [i adnotat implicit cu
informa]ii pri(ind situa]ia unei (ariabile/ dac! ea este sau nu declarat! 0deci poate sau
nu furni+a o (aloare1 `n momentul cnd ea este referit! dintr'o expresie& 3nforma]iile
care ar trebui s! adnote+e arborele sintactic sunt `ns! p!strate direct `n tabela de
simboluri&
Cititorii interesa]i de o implementare care crea+! efecti( un arbore sintactic adnotat pot
consulta lucrarea I% Compact 9uide )o ;ex X BaccI de ).omas Fiemann$ disponibil!
gratuit pe 3nternet$ pe site'ul epapers&com& Fot!m totu[i c! exemplele de acolo nu pot fi
folosite pe un sistem ;inux f!r! unele modific!ri& Vom `ncerca s! public!m `n anexa
acestui (olum sau `n partea a doua [i unele surse corectate pentru Flex @ Bison 0deci
destinate platformei ;inux1 pe care le'am rescris documentndu'ne din lucrarea citat!&
*odific!rile 6canner'ului 0anali+orului lexical1
Qi scanerul 0anali+orul lexical1 trebuie modificat pentru a returna denumirea 0sub form!
de string a &&&1 fiec!rui identificator$ ea fiind practic (aloarea semantic! 0d&p&d&(& al
semanticii statice1 asociat! fiec!rui identificator& %ceast! (aloare semantic! (a fi
returnat! printr'o (ariabil! global! numit! yylval. )ipul acestei (ariabile este un tip
reuniune 0union ca `n C1 creat cu directi(a 'union plasat! `n fi[ierul cu descrierea
parserului& "up! ca+ [i tipul (alorii semantice de comunicat de la scaner la parser$
aceasta (a fi plasat! `ntr'un membru corespun+!tor ca tip al reuniunii& "ac! declara]ia
IunionI'ului (a fi
%union { char *id;
}
50
(aloarea semantic! (a trebui copiat! din (ariabila global! yytext 0 care con]ine
`ntotdeauna textul utimului atom lexical1 `n yylval.id & "eoarece exemplul de mai =os
folose[te func]ia strdup din biblioteca string&.$ aceast! bibliotec! trebuie s! fie [i ea
inclus!& Fi[ierul cu descrierea scanerului$ care (a fi prelucrat de ;ex @ Flex $ (a con]ine/
%{
#include <string.h> /* fiind necesar strdup */
#include "simple.tab.h" /* cu definitiile atomilor si cu yylval */
%}
DGT [0-9]
D [a-z][a-z0-9]*
%%
":=" { return(ASSGNOP); }
{DGT}+ { return(NUMBER); }
do { return(DO); }
else { return(ELSE); }
end { return(END); }
fi { return(F); }
if { return(F); }
in { return(N); }
integer { return(NTEGER); }
let { return(LET); }
read { return(READ); }
skip { return(SKP); }
then { return(THEN); }
while { return(WHLE); }
write { return(WRTE); }
{D} { yylval.! # ($%ar *) s&r!'((yy&)x&)*
return(DENTFER);}
[ \t\n]+ /* eat up whitespace - pentru a consuma albitura, blancurile, tab-urile */
. { return(yytext[0]);}
%%
Depre+entarea intermediar!
*ulte compilatoare con(ertesc codul surs! `ntr'o repre+entare intermediar! `n cursul
acestei fa+e de traducere [i (erificare a restric]iilor contextuale& #e aceast!
repre+entare intermediar! operea+! gramatica cu atribute [i optimi+atorul arborelui 0sau
al repre+ent!rii intermediare1& 2n exemplul nostru repre+entarea intermediar! implicit!
este c.iar arborele sintactic& #ractic el este construit ramur! cu ramur! pe sti(!$ pe
m!sura parcurgerii& "e[i deocamdat! el este doar implicit$ cu mici modific!ri de program
el poate fi construit explicit$ apelnd pentru fiecare structur! sintactic! func]ii care
creea+! nodul respecti( sau modific! repre+entarea&
%lte solu]ii r!spndite pentru reali+area repre+ent!rii intermediare includ arborii de
sintax! abstract!$ cod cu trei adrese$ cunoscutele ^uadruple [i scrierea postfix
0operatorii se scriu dup! operan+i1& 6unt folosite `n di(erse etape intermediare ale
compil!rii&
51
2n acest exemplu de implementare a limba=ului simple (om s!ri peste etapa gener!rii
repre+ent!rii intermediare a programului 0deci [i peste optimi+area ei1 [i (om trece
direct la generarea de cod& "e altfel principiile ilustrate mai departe la generarea de cod
se pot aplica foarte bine [i la generarea de repre+ent!ri intermediare 0de exemplu la
generarea de ^uadruple1&
2n urma modific!rilor indicate `n acest capitol$ fi[ierele dumnea(oastr! ar putea ar!ta a
[a/
6imple&lex
%{
#include <string.h> /* Aici este functia "strdup" */
#include "simple.tab.h" /* Definitiile atomilor si yylval */
%}
DGT [0-9]
D [a-z][a-z0-9]*
%%
":=" { return(ASSGNOP); }
{DGT}+ { return(NUMBER); }
do { return(DO); }
else { return(ELSE); }
end { return(END); }
fi { return(F); }
if { return(F); }
in { return(N); }
integer { return(NTEGER); }
let { return(LET); }
read { return(READ); }
skip { return(SKP); }
then { return(THEN); }
while { return(WHLE); }
write { return(WRTE); }
{D} { yylval.id = (char *) strdup (yytext);
return (DENTFER); }
[ \n\t]+ /* eat up whitespace - pentru a consuma albitura, blancurile, tab-urile */
. { return(yytext[0]); }
%%
6imple&-
/* Yacc/bison file for Simple */
/* Dan Popa, dupa Anthony A Aabey, Comp. Constr with Flex and Bison, cap 4 pg 14 */
/* C and parser declarations */
%{
#include <stdlib.h> /*Contine malloc folosit de tab. de simboluri ST.h*/
#include <string.h> /*Contine strcmp folosit de tab. de simboluri ST.h*/
#include <stdio.h> /* Pentru mesajele de eroare ? */
#include "ST.h" /* Modulul cu Tabela de simboluri */
#define YYDEBUG 1 /* For debugging */
52
int errors;
install (char *sym_name )
{ symrec *s;
s = getsym (sym_name);
if (s == 0)
s = putsym (sym_name);
else
{ errors++;
printf( "%s is already defined \n", sym_name );
}
}
context_check(char * sym_name )
{ if ( getsym(sym_name) == 0 )
printf ("%s is an undeclared identifier \n", sym_name);
}
/* Sectiunea continua cu: Parser declarations */
/* Deoarece scanerul generat de Lex va returna identificatori, */
/* iar noi vom utiliza o semantica statica, o inregistrare */
/* numita "semantic record" e necesara pentru a stoca valoarea */
/* iar DENT este asociat cu acest "semantic record". */
%}
%start program
%union { /* SEMANTC RECORD */
char *id; /*for returning identifiers */
}
%token LET NTEGER N
%token SKP F THEN ELSE END WHLE DO READ WRTE F
%token ASSGNOP NUMBER
%token <id> DENTFER /* Simple identifier */
%left '-' '+'
%left '*' '/'
%right '^'
%%
program : LET declarations N commands END ;
declarations : /* empty */
| NTEGER id_seq DENTFER '.' { install($3); }
;
id_seq : /* empty */
| id_seq DENTFER ',' {install($2); }
;
commands : /* empty */
| commands command ';'
;
command : SKP
| READ DENTFER { context_check ($2); }
| WRTE exp
| DENTFER ASSGNOP exp { context_check ($1); }
| F exp THEN commands ELSE commands F
| WHLE exp DO commands END
;
exp : NUMBER
| DENTFER { context_check ($1); }
| exp '<' exp
55
| exp '=' exp
| exp '>' exp
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| exp '^' exp
| '(' exp ')'
;
%%
/* C subroutines */
int main (int argc, char * argv[] )
{extern FLE *yyin;
++argv; --argc;
yyin = fopen( argv[0], "r" );
yydebug = 1 ;
/* errors = 0 ; */
yyparse();
}
yyerror (char *s) /* Called by yyparse on error */
{
print("%s\n", s);
}

54
Capitolul 5
,ptimi+area
<ste teoretic posibil s! transform!m arborele de deri(are pentru a'i reduce dimensiunile
sau pentru a oferi generatorului de cod oportunitatea de a produce un cod mai eficient&
2ntruct compilatorul din exemplul nostru nu produce 0dect implicit1 arborele$ nu (om
ilustra aceste transform!ri de arbore& 2n sc.imb (om pre+enta asemenea transform!ri
sub forma codului surs! corespun+!tor instruc]iunilor neoptimi+ate [i respecti(
optimi+ate& %ceast! pre+entare ignor! deliberat faptul c! unele compilatoare fac dou!
feluri de optimi+!ri$ unele asupra arboreluli altele asupra codului generat& %ceste dou!
feluri de optimi+!ri$ nu se pot substitui una pe alta&
'valuarea constantelor din timpul compil!rii `[i propune s! precalcule+e tot ce se
poate pe ba+a (alorilor constante cunoscute la momentul compil!rii$ care apar `n
expresii& 3at! cum s'ar transforma ele/
j := 5 + K + 6 ; --> j := 11 + K;
m := 4 ; n := m + 3; --> m := 4; n := 7;
'liminarea calculelor repetate din bucle$ scoaterea lor `nafara buclei$ repre+int! o
alt! optimi+are& Demarca]i parante+a din ciclu ce (a trebui e(aluat! inutil [i repetat&
while ( index < maxim ) do
input sales;
value := salex * ( +ar,-'( + &ax );
output := value;
index := index + 1;
end;
(odul ar putea fi optimi)at *n felul urm\tor+
temp := ( mark_up + tax );
while ( index < maxim ) do
input sales;
value := salex * &)+(;
output := value;
index := index + 1;
end;
'liminarea variabilei contor+ Cea mai mare parte din timpul de calcul al programelor
este ocupat cu execu]ia calculelor din bucle& ,ptimi+area buclelor este deci o `mbun!t!'
]ire semnificati(!& >+ual$ (ariabila contor a buclei este folosit! doar `n interiorul buclei&
2n acest ca+ este mai bine ca ea s! poat! fi stocat! `ntr'un registru `n loc s! fie stocat!
`n memorie& 2n plus$ dac! ea este folosit! doar ca indice pentru un (ector 0ceea ce
implic! o `nmul]ire [i o adunare la fiecare rotire a buclei1 optimi+area const! `n a ini]ia'
li+a (ariabila cu adresa de `nceput a (ectorului [i a o IincrementaI cu lungimea unui
element de (ector& , bucl!/
55
For := 1 to 10 do
A[] := A[] + E
,evine +
For := adresa primului element din A
&o adresa ultimului element din A
by dimensiunea unui element din A !o
A[] := A[] + E
'liminarea subexpresiilor comune dintr'un [ir de expresii prin calcularea (alorii lor
doar o singur! dat!/
A := 6 * (B+C);
D := 3 + 7 * (B+C);
E := A * (B+C);
,evine+
TEMP := B + C;
A := 6 * TEMP;
D := 3 * 7 * TEMP;
E := A * TEMP;
-nlocuirea unor *nmul]iri cu opera]ii mia rapide+
2*x --> x + x
2*x --> shift left x
.tili)area identit\]ilor matematice+
a*b + a*c --> a*(b+c)
a - b --> a + ( - b )
Fu (om `n+estra implementarea noastr! de 6imple cu un optimi+ator de cod&
58
Capitolul 8
*a[ini Virtuale
>n calculator construit efecti( din componente electronice este considerat o ma[in! de
calcul real!& <l exist! fi+ic& "in punct de (edere al programatorul$ setul de instruc]iuni
ale acelui .ardAare define[te clar ma[ina de calcul& >n sistem de operare este un
program construit peste resursele oferite de ma[ina real!$ pentru a fi gestionarul
acestora [i pentru a oferi o serie de alte ser(icii$ de exemplu apelurile de sistem&
6er(iciile oferite de sistemul de operare$ practic instruc]iuni aparte ce pot figura `ntr'un
program sau altul$ definesc de data aceasta o ma[in! (irtual!& <a nu exist! fi+ic& Fu
exist! circuite electronice speciali+ate care s! ofere acele ser(icii&
>n limba= de programare pune la dispo+i]ie un set de date [i un set de instruc]iuni
exprimabile printr'o anume sintax!& >n .ardAare capabil s! execute direct acele
instruc]iuni asupra datelor ar fi un computer real& 2n teorie este posibil s! (orbim de o
ma[n! #ascal$ o ma[in! 6c.eme sau una Fort.& Cea din urm! e c.iar implementat!
`ntr'un cip speciali+at& #ractic$ pentru progarmator nu contea+! dac! ma[ina este real!
sau (irtual!& Cei care au trecut de la C la Wa(a au constatat c! trecerea de la
programarea unei ma[ini reale la programarea uneia (irtuale nu'i deran=a cu nimic& 3ar
pentru programator ma[ina e sinonim! cu limba=ul computerului& ;imba=ul de
programare define[te practic un computer imaginar$ (irtual sau araeori real$ cu care
interac]ione+i programndu'l& ,rice ma[in! (irtual!$ programabil!$ capabil! s!
manipule+e date$ trebuie s! aib! o modalitate de a stoca att datele ct [i programul&
"ac! o implemente+i `n alt limba= trebuie s! specifici `n acest alt limba= cum se execut!
instruc]iunile ma[ini (irtuale asupra datelor ei&
"e obicei 0obicei care a fost preluat de limba=e interpretate ca Basic$ Wa(a1 `ntre
programator$ care dialog.ea+! cu o ma[in! (irtual! ba+at! pe un limba= de ni(el `nalt [i
ma[ina (irtual! care e sistemul de operare se interpune o alt! ma[in! (irtual!&
Compilatorul limba=ului poate genera altfel de cod 0b-tecode1 [i pe acesta trebuie s!'l
rule+e cine(a& %ceast! ma[in! (irtual! este a[a'+isul Irun'time engineI al limba=ului&
Complexitatea acesteia poate (aria de la nimic 0ca+ul Fortranului [i al acelor
compilatoare care generea+! cod direct pentru procesor sau pentru ma[ina (irtual!
care este sistemul de operare1 la acele sisteme extrem de sofisticate$ a(nd manager
de memorie [i mecanisme de intercomunicare `ntre procese cum e ca+ul unor limba=e
de programare concurente$ de exemplu 6D&
Dun'time s-stem'ul pentru limba=ul 6imple (a include o component! de procesare
capabil! s! execute cod$ implementat! ca un mic interpretor interior [i o +on! de date `n
care (alorile atribuite (ariabilelor sunt accesate printr'un deplasament raportat la
`nceputul +onei& < practic un (ector&
Fot!/ unele programe utili+ator pot fi considerate de asemenea ca o clas! aparte de
ma[ini (irtuale&
54
).e 60tacH1 *ac.ine ' , ma[in! (irtual! cu sti(!
0adaptare dup! FiHlaus Tirt.$ Algorithms + Data Structure = Programs
#rentice'Mall$ <ngleAood Clifs$ F&W&$ 1748&1
6'ma[ina este o ma[in! cu sti(! proiectat! pentru a simplifica implementarea limba=elor
cu structur! de bloc& <a ofer! o alcare dinamic! sub forma unei sti(e de `nregistr!ri de
acti(are& 0Care corespund$ nota bene$ blocurilor&1 %ceste `nregistr!ri de acti(are sunt
legate `ntre ele pentru a permite tipi+area static! [i con]in [i informa]iile de context
necesare procedurilor&
/rgani)area ma[inii+ 6'ma[ina const! `n dou! +one de stocare$ una dedicat!
programului [i numit! ( 0organi+at! ca un (ector read'onl-1 [i o +on! de date S
0organi+at! ca o sti(!1& <xist! patru regi[triY un registru de instruc]iuni 01 care con]ine
instruc]iunea ce trebuie interpretat!$ un registru IstacH'pointerI " care con]ine adresa
ultimului element al sti(ei$ 2(, acel Iprogram'counterI care con]ine adresa urm!toarei
instruc]iuni de adus `n (ederea interpret!rii [i registrul `nregistr!rii de acti(are curente$
%1, cel care con]ine adresa ba+ei `nregistr!rii de acti(are aferente procedurii care e `n
curs de interpretare& Fiecare loca]ie din ( este capabil! s! stoc.e+e o instruc]iune&
Fiecare loca]ie din S este capabil! s! stoc.e+e o adres! sau un `ntreg& Fiecare instruc'
]iune const! `n trei informa]ii$ trei cmpuri/ un cod al opera]iei [i doi parametri&
Setul de instruc]iuni+ (-codurile formea+! limba=ul ma[in! al 6'ma[inii& 6'codurile
ocup! fiecare cte patru b-tes& #rimul b-te este codul opera]iei 0op'code1& <xist! nou!
astfel de instruc]iuni 06'coduri1 de ba+!$ fiecare cu un cod de opera]ie diferit& %l doilea
b-te al 6'codului con]ine ori un +ero$ ori un fel de offset lexical$ ori un cod de condi]ie
pentru instruc]iunile de salt condi]ionat& >ltimii doi b-tes lua]i `mpreun! formea+! un
`ntreg pe 18 bi]i cu rolul de operand& <l poate fi o constant! 0Iliteral (alueI1$ un offset al
po+i]iei unei (ariabile pe sti(! pornind de la ba+a$ adresa loca]iei altui 6'cod$ un num!r
de opera]ie 0RGR1$ ori un alt num!r special al c!rui sens e (alabil doar pentru un 6'cod cu
anumit cod de opera]ie&
(omentarii+ < normal ca di(ersele feluri de instruc]iuni 06'coduri1 s! se disting! prin
codul opera]iei& , adunare e ce(a diferit de un salt$ de exemplu& ;a rndul lor salturile
condi]ionate pot fi condi]ionate de faptul c! o (aloare este +ero$ sau nu este +ero deci
oricum a(em mai multe categorii de instruc]iuni de salt& %l doilea octet diferen]ia+!
tocmai instruc]iunile din aceea[i familie$ cu acela[i cod de opera]ie& 3nstruc]iunile pot s!
manipule+e [i adrese sau numere de 18 bi]i ori de 2 b-tes deci mai poate fi ne(oie de
`nc! doi b-tes suplimentari pentru corpul instruc]iunii& #ractica arat! c! la un asemenea
limba= simplu nu e ne(oie de mai mul]i b-tes pentru un 6'code& )oate instruc]iunile$
indiferent de codul de opera]ie din primul octet n'au ne(oie de mai mult de 5 octe]i
pentru a a(ea `n continuarea op'code'ului informa]iile necesare&
6emantica$ ac]iunea fiec!reia dintre instruc]iuni este descris! mai =os$ folosind un
5:
amestec de limba= natural [i nota]ie formal!& %ceast! nota]ie inspirat! din limba=ele de
programare de ni(el `nalt este folosit! pentru a preci+a sc.imb!rile care au loc `n
memoria de date [i `n registrele ma[inii cu sti(!& ,bser(a]i c! instruc]iunile de acces la
date 0practic la (ariabilele locale ale procedurilor1 au ne(oie de un deplasament
raportat la `nregistrarea de acti(are curent! 0arat! a cta (ariabil! local e implicat!1 [i
de diferen]a de ni(el dintre ni(elul referin]ei [i ni(elul declara]iei 0era posibil de exemplu
ca (ariabila s! fi fost declarat! `ntr'o procedur! exterioar!$ dar contea+! exact `n a cta
deoarece aceasta determin! po+i]ia ei pe sti(! `n `nregistrarea de acti(are
corespun+!toare1& %pelurile de procedur! au ne(oie de adresa codului apelat [i de
asemenea de diferen]a dintre ni(elul referin]ei [i cel al declara]iei&
./s&r'$&o/ 0()ra/!s 1o++)/&s
/O operations
READ 0,N nput integer in to location N: S(N) := nput
WRTE Output top of stack: Output := S(T); T:= T-1
OPR Arithmetic and logical operations
0,0 process and function, return operation
T:= AR-1; AR:= S(T+2); P:= S(T+3)
ADD ADD: S(T-1) := S(T-1) + S(T); T := T-1
SUB SUBTRACT: S(T-1) := S(T-1) - S(T); T := T-1
MULT MULTPLY: S(T-1) := S(T-1) * S(T); T := T-1
DV DVDE: S(T-1) := S(T-1) / S(T); T := T-1
MOD MOD: S(T-1) := S(T-1) mod S(T); T := T-1
EQ TEST EQUAL:
S(T-1) := if S(T-1) = S(T) then 1 else 0; T:= T-1
LT TEST LESS THAN:
S(T-1) := if S(T-1) < S(T) then 1 else 0; T:= T-1
GT TEST GREATER THAN:
S(T-1) := if S(T-1) > S(T) then 1 else 0; T:= T-1
LD_NT 0,N LOAD literal value onto stack: T:= T+1; S(T):= N
LD_VAR L,N LOAD value of variable at level offset L, base
offset N in stack onto top of stack
T:= T + 1; S(T):= S(f(L,AR)+N)+3
STORE L,N store value on top of stack into variable location
at level offset L, base offset N in stack
S(f(ld,AR)+os+3):= S(T); T:= T - 1
CAL L,N call PROC or FUNC at S-code location N declared
at level offset L
S(T+1):= f(ld,AR); { Static Link }
S(T+2):= AR; { Dynamic Link }
S(T+3):= P; { Return Address }
AR:= T+1; { Activation Record }
P:= cos; { Program Counter }
T:= T+3 { Stack Top }
CAL 255,0 call procedure address in memory: POP address, PUSH return
address, JUMP to address
DATA 0,NN ADD NN to stack pointer T := T+NN
GOTO 0,N JUMP: P := N
JMP_FALSE C,N JUMP: if S(T) = C then P:= N; T:= T-1
%ici diferen]a de ni(el static `ntre procedura curent! [i cea apelat! este notat! cu ld&
57
Cu os este notat offsetul 0deplasamentu1 `n cadrul `nregistr!rii de acti(are curente [i tot ld este diferen]a
de ni(el static `ntre `nregistrarea de acti(are curent! [i `nregistrarea de acti(are `n care (a fi stocat!
(aloarea& Func]ia f0ld$a1 este implementarea urm!toarei expresii condi]ionale& , pute]i scrie ca o func]ie cu
acolad! daca dori]i&
f(i,a) = if i=0 then a else f(i-1,S(a))
3magina]i'(! c! fiecare `nregistrare de acti(are are la `nceputul ei$ la adresa a$ un
pointer c!tre precedenta `nregistrare de acti(are& #ractic 60a1 (a fi adresa `nregistr!rii
de acti(are precedente&
6e merge pe acest [ir de `nregistr!ri de acti(are `napoi$ pas cu pas$ p`n! a=ungem la
prima& %dresa ei este la ba+a sti(ei&
3unc]ionarea+ Degistrii ma[inii cu sti(! sunt `ni]iali+a]i dup! cum urmea+!/
P = 0. { Program Counter - ndica instructiunea curenta}
AR = 0; { Activation Record ndica inregistrarea de activare curenta}
T = 2; { Stack Top Virful stivei}
S[0] := 0; { Static Link Legatura statica}
S[1] := 0; { Static Dynamic Link Legatura dinamica}
S[2] := 0; { Return Address Adresa de reintoarcere }
*a[ina aduce periodic `n registrul 3D instruc]iunea indicat! de registrul #C$
incrementea+! registrul #C [i execut! instruc]iunea& )otul se repet! p`n! cnd #C'ul
a=unge s! con]in! +ero sau este `ntlnit! [i executat! o instruc]iune M%;)& 2ntr'un
pseudocod inspirat de #ascal$0parte a unei masini (irtuale1 ciclul s'ar scrie/
REPEAT
R:= C(P); (* Fetch *)
PC:= PC+1;
interpret(R); (* Execute*)
UNTL R = "Halt" or PC = 0
%ceast! bucl! numit! [i Ifetc.'execute loopI are de f!cut deci dou! lucruri `nainte de a
executa 0interpreta1 o instruc]iune/ s! aduc! op'codul ei `n registrul de instruc]iuni [i s!
po+i]ione+e contorul de program #C astfel ca el s! indice octetul urm!tor& %ici (a g!si
subrutina IinterpretI b-te'ul al doilea& Decuperarea acestor al doilea [i la ne(oie$ al
treilea [i al patrulea b-te din 6'codul instruc]iunii curente r!mn `n sarcina subrutinei
IinterpretI& <a poate dup! ca+ s! aduc! spre utili+are unu$ doi sau trei dintre ace[ti
b-tes sau c.iar pe niciunul$ dar oricum (a face (a trebui s! incremente+e registrul #C
astfel `nct el s! indice op'cod'ul urm!tor& #ractic dup! terminarea subrutinei IinterpretI
#C'ul (a ar!ta o adres! cu 5 b-tes mai departe$ ea fiind adresa urm!toarei instruc]iuni&
,p'codul de aici (a fi `nc!rcat `n 3D la urm!torul Ifetc.I atunci cnd se reia bucla& Qi tot
a[a mai departe&
*odulul I*a[ina Virtual! cu 6ti(!I$ 6*&.
3mplementarea ma[inii cu sti(! de care a(em ne(oie e dat! `n continuare& 6etul de
instruc]iuni implementate [i structura unei instruc]iuni sunt definite dup! cum urmea+!/
40
/* OPERATONS: nternal Representation */
enum code_ops { HALT, STORE, JMP_FALSE, GOTO,
DATA, LD_NT, LD_VAR,
READ_NT, WRTE_NT,
LT, EQ, GT, ADD, SUB, MULT, DV, PWR };
/* OPERATONS: External Representation */
char *op_name[] = {"halt", "store", "jmp_false", "goto",
"data", "ld_int", "ld_var",
"in_int", "out_int",
"lt", "eq", "gt", "add", "sub", "mult", "div", "pwr" };
struct instruction
{
enum code_ops op;
int arg;
};
*emoria este separat! `n dou! segmente$ un segment destinat codului [i altul destinat
deopotri(! sti(ei [i (ariabilelor locale create dinamic `n cursul execu]iei&
struct instruction code[999];
int stack[999];
>rmea+! defini]iile regi[trilorY contorul de instruc]iuni 0eng& Iprogram counterI1 pc$
registrul de instruc]iuni ir, registrul indicator al `nregistr!rii de acti(are 0 eng& Iacti(ation
recordI1 curente numit ar [i registrul care arat! spre (rful sti(ei$ numit top& 2n paginile
anterioare fusese numit ) dar este (orba de acela[i registru& <ste uneori numit [i stacH
pointer ' indicator de sti(!$ din aceast! cau+! fiind notat 6# la unele procesoare&
Degistrul ar indic! `nceputul por]iunii din sti(! care (a corespunde ultimei proceduri
acti(e& "e (ariabila c. (om a(ea ne(oie mai tr+iu dar o declar!m de=a aici&
int pc = 0 ;
struct instruction ir ;
int ar = 0 ;
int top = 0 ;
char ch ;
Ciclul Ifetc.'executeI se repet! pn! la `ntlnirea unei instruc]iuni speciale$ numit!
M%;)$ instruc]iune care exist! [i la procesoarele reale&
void fetch_execute_cycle()
{
do { /* Fetch */
ir = code[pc++];
/* Execute */
switch (ir.op) {
41
case HALT : printf( "halt\n" ); break;
case READ_NT : printf( "nput: " );
scanf( "%ld", &stack[ar+ir.arg] ); break;
case WRTE_NT : printf( "Output: %d\n", stack[top--] ); break;
case STORE : stack[ir.arg] = stack[top--]; break;
case JMP_FALSE : if ( stack[top--] == 0 )
pc = ir.arg; break;
case GOTO : pc = ir.arg; break;
case DATA : top = top + ir.arg; break;
case LD_NT : stack[++top] = ir.arg; break;
case LD_VAR : stack[++top] = stack[ar+ir.arg]; break;
case LT : if ( stack[top-1] < stack[top] )
stack[--top] = 1;
else stack[--top] = 0; break;
case EQ : if ( stack[top-1] == stack[top] )
stack[--top] = 1;
else stack[--top] = 0; break;
case GT : if ( stack[top-1] > stack[top] )
stack[--top] = 1;
else stack[--top] = 0;
top--; break;
case ADD : stack[top-1] = stack[top-1] + stack[top];
top--;
break;
case SUB : stack[top-1] = stack[top-1] - stack[top];
top--;
break;
case MULT : stack[top-1] = stack[top-1] * stack[top];
top--;
break;
case DV : stack[top-1] = stack[top-1] / stack[top];
top--;
break;
case PWR : s&a$,[&o(-2] # s&a$,[&o(-2] * s&a$,[&o(]* 3* 4)& $or)$&a a$5 *3
top--;
break;
default : printf( "%snternal Error: Memory Dump\n" );
break;
}
}
while (ir.op != HALT);
}
*a[ina (irtual! de mai sus are ne(oie de o corectur! deoarece tentati(a ei de a
executa instruc]iunea #TD duce la calculul unui produs nu la cel al unei ridic!ri la
putere& Deali+area acestei corecturi este l!sat! pe seama cititorului$ ca exerci]iu&
#entru depanarea buclei Ifetc.'executeI pute]i scrie [i urm!toarele linii de program `n
locul comentariului @] Fetc. ]@ sau imediat dup! acesta&
printf ( "PC = %23d R.arg =%8d AR = %23d Top = %3d , %8d \n",
pc, ir.arg, ar, top , stack[top] );
42
*odific!ri ale parserului
6unt necesare modific!ri `n fi[ierul anterior cu specifica]ii Bacc@Bison astfel ca
programul principal s! apele+e ma[ina (irtual! pentru a rula programul care a fost
anali+at 0IparsatI1 cu succes& %d!uga]i `n sec]iunea *%3F a parserului 6imple&- linile/
printf ( "Parse Completed\n" );
if ( errors == 0 )
{ print_code ();
fetch_execute_cycle();
}
2ntreaga func]ie main din fi[ierul 6imple&- (a ar!ta a[a/
/*=========================================================================
MAN
=========================================================================*/
main( int argc, char *argv[] )
{ extern FLE *yyin;
++argv; --argc;
yyin = fopen( argv[0], "r" );
/*yydebug = 1;*/
errors = 0;
yyparse ();
printf ( "Parse Completed\n" );
if ( errors == 0 )
{ print_code ();
fetch_execute_cycle();
}
}
%ceste modific!ri (or permite s! fie executat pe ma[ina (irtual! codul generat& "e
generarea codului se ocup! capitolul urm!tor&
45
>n exemplu de cod produs `n urma compil!rii/
0: data 1
1: in_int 0
2: ld_var 0
3: ld_int 10
4: lt 0
5: jmp_false 9
6: ld_int 1
7: store 1
8: goto 9
9: ld_var 0
10: ld_int 10
11: lt 0
12: jmp_false 22
13: ld_int 5
14: ld_var 1
15: mult 0
16: store 1
17: ld_var 0
18: ld_int 1
19: add 0
20: store 0
21: goto 9
22: ld_var 0
23: out_int 0
24: ld_var 1
25: out_int 0
26: halt 0
Figura 7.2: Cod generat
44
Capitolul 4
9enerarea codului
#e m!sur! ce programul surs! este parcurs 0de c!tre parser1 el este tradus `ntr'o form!
intern!& Frec(ent folosit! este forma de arbore& %cesta poate fi creat explicit sau
parcurs implict$ ca o sec(en]! de apeluri de subprograme& 2n exemplul nostru arborele
(a fi implicit& #ot exista [i alte forme interne& ;a unele compilatoare$ `nainte de codul
obiect generat$ exist! o (ariant! a lui `ntr'un limba= care seam!n! cu limba=ul de
asamblare& Codul `n form! intern! este `n final transformat `n cod obiect de c!tre
generatorul de cod& )ipic$ codul obiect este un program pentru o minuscul! ma[in!
(irtual!& %lteori el este c.iar cod pentru procesorul .ardAare al sistemului& #entru
execu]ia programelor scrise `n 6imple (om folosi ma[ina (irtual! descris! anterior$
format! din trei segmente 0de memorie1Y un segment de date$ un segment de cod [i o
stiv\$ aceasta fiindu'ne util! pentru e(aluarea expresiilor& ;a implement!ri de limba=e
care folosesc subprograme sti(a ser(e[te [i pentru controlul execu]iei acestora [i
stocarea (alorilor locale&
6egmentul de date este cel care stoc.ea+! (alorile (ariabilelor&Fiecare (ariabil! are
asociat! o loca]ie `n care se (a stoca (aloarea ei& "eci o parte din acti(itatea
generatorului de cod (a consta `n atribuirea de adrese pentru fiecare (ariabil!&
6egmentul de cod con]ine sec(en]a tuturor instruc]iunilor programului& Constantele din
program sunt stocate tot `n segmentul de cod$ lucru posibil deoarece (alorile lor nu se
sc.imb! iar segmentul de cod este din punct de (edere al ma[inii (irtuale Iread'onl-I&
6ti(a expresiilor este o sti(! folosit! `n special pentru a p!stra (alorile intermediare care
apar `n timpul e(alu!rii expresiilor& "atorit! pre+en]ei ei$ ma[ina (irtual! a limba=ului
6imple este numit! o ma[in! cu sti(! sau 6'ma[in! 0eng& 6tacH'mac.ine1&
)raducerea declara]iilor
"eclara]iile definesc contextul e(alu!rii expresiilor& #entru a re+er(a spa]iul pe sti(!
necesar (ariabilelor (om folosi instruc]iunea "%)% a ma[inii (irtuale$ creat! c.iar `n
acest scop& Dolul ei este s! I`mping!I capul sti(ei mai departe l!snd loc pe sti(!
pentru num!rul de (ariabile cerut& 2n 6imple toate (ariabilele fiind de acela[i tip$ spa]iul
ocupat pe sti(! este propor]ional cu num!rul lor [i e suficient s! d!m acest num!r ca
parametru al instruc]iunii "%)%& <l (a fi p!strat `n segmentul de cod ca argument al
instruc]iunii "%)%&
"ar (ariabilele (or fi stocate `n segmentul de date& %cesta fiind practic un (ector
declarat `n C$ num!r!toarea (ariabilelor (a `ncepe cu 0$ prima (ariabil! ocupnd po+i]ia
0$ a doua po+i]ia 1$ a treia po+i]ia 2 [&a&m&d& "eci se (a compila/
integer x,y,z. ---> DATA 2 iar integer n,x. ---> DATA 1
45
)raducerea instruc]iunilor
3nstruc]iunile de atribuire$ if$ A.ile$ read [i Arite sunt traduse dup! regulile de mai =os/
x := expr cod pentru expr
STORE X
if cond then cod pentru cond
S1 JMP_FALSE L1
else cod pentru S1
S2 BR L2
end L1: cod pentru S2
L2:
while cond do L1: cod pentru cond
S JMP_FALSE L2
end cod pentru S
GOTO L1
L2:
read X N_NT X
write expr cod pentru expr
OUT_NT
,bser(a]i c! anumite adrese cum sunt ;1 [i ;2 pentru if sau ;2 pentru A.ile nu sunt
imediat disponibile$ (aloarea lor fiind determinat! de lungimea unor seg(en]e de cod
care n'au fost `nc! generate& <le (or fi completate atunci cnd (aloarea lor exact!
de(ine cunoscut!& ,pera]ia se nume[te IbacH'patc.ingI [i (a fi executat! de o
subrutin! care se apelea+! `n finalul compil!rii structurii respecti(e& 2n exemplul nostru
aceast! subrutin! se (a numi c.iar back#patc&
)raducerea expresiilor
<xpresiile (or fi e(aluate folosind sti(a& ;a traducerea lor se (or genera instruc]iuni ale
ma[inii (irtuale cum sunt ;" [i ;"?3F)& Codul pentru un operator (a fi generat dup!
codurile pentru operan+i& #ractic traducerea transform! expresia obi[nuit! `n forma ei
polone+! postfixat! 0cu operatorul dup! operan+i1 iar e(aluarea se (a face de c!tre ma'
[ina (irtual! care implementea+! regulile/ 11 constanta sau (ariabila se pune pe sti(! [i
21 operatorul scoate din sti(! c]i operan+i are ne(oie$ face calculul [i pune re+ultatul
tot `n sti(!& Cu aceste reguli simpla parcurgere a unei expresii duce la plasarea (alorii ei
pe sti(!& Ca o consecin]!$ pentru ma[ina (irtual!$ simpla execu]ie a codului asociat
expresiei (a duce la punerea re+ultatului `n sti(!& )raducerea se fece dup! regulile/
constanta LD_NT constanta
variabila LD_VAR variabila
e1 op e2 cod pentru e1
cod pentru e2
cod pentru op
48
*odulul generator de cod / C9&.
6egmentul de date `ncepe cu loca]ia 0 & De+er(area spa]iului `n segmentul de date se
(a face apelnd func]ia data#location care (a returna adresa loca]iei nou re+er(ate&
Variabila data#o!!set arat! totdeauna urm!toarea loca]ie liber! `n segmentul de date&
2ntruct datele ocup! exact o loca]ie `n segment$ tot ce are de f!cut data#location este
s! returne+e adresa loca]iei curente libere [i apoi s! incremente+e (ariabila data#o!!set.
int data_offset = 0;
int data_location() { return data_offset++; }
6egemntul de cod are [i el loca]iile numerotate `ncepnd cu +ero& %ici `ns! alocarea de
spa]iu se (a face apelnd subrutina reserve#loc care (a returna adresa loca]iei g!site&
0#rima loca]ie liber!&1 "ac! nu mai (rem s! aloc!m dar ne interesea+! la ce adres! (a
`ncepe sec(en]a de cod urm!toare 0ca `n ca+ul `n care acolo ar fi o etic.et! ;21 (om
apela func]ia gen#label care nu face dec!t s! returne+e (aloarea adresei urm!toarei
loca]ii libere$dar f!r! s! aloce spa]iul&
int code_offset = 0;
int reserve_loc()
{
return code_offset++;
}
int gen_label()
{
return code_offset;
}
Func]iile reserve#loc [i gen#label ne (or ser(i la bacH'patc.ing'ul codului&
Func]iile gen#code [i back#patc sunt folosite `n procesul gener!rii codului& gen#code
generea+! codul unei instruc]iuni `n po+i]ia curent! 0code?offset1 `n segmentul de cod&
2n sc.imb back#patc este folosit! la a genera complet!ri ale codului la cte'o adres!
re+er(at! dinainte$ adresa fiindu'i dat! ca prim parametru&
void gen_code( enum code_ops operation, int arg )
{ code[code_offset].op = operation;
code[code_offset++].arg = arg;
}
void back_patch( int addr, enum code_ops operation, int arg )
{
code[addr].op = operation;
code[addr].arg = arg;
}
44
*odific!ri ale modulului )abela de 6imboluri/ 6)&.
Formatul articolelor din tabela de simboluri trebuie extins& <l (a con]ine pentru fiecare
(ariabil! din tabel! [i offset'ul 0po+i]ia1 acesteia `n segmentul de date& %ceasta e adresa
+onei `n care (ariabila `[i p!strea+! (aloarea& 3ar func]ia putsym de ad!ugare a
simbolului `n tabel! (a fi [i ea extins! pentru a `ndeplini sarcina de plasare a offset'ului
`n articolul din tabel! corespun+!tor (ariabilei&
struct symrec
{
char *name; /* numele simbolului - identificatorul variabilei */
int offset; /* offset in segmentul de date */
struct symrec *next; /* legatura cu urmatorul din lista */
};
...
symrec * putsym (char *sym_name)
{
symrec *ptr;
ptr = (symrec *) malloc (sizeof(symrec));
ptr->name = (char *) malloc (strlen(sym_name)+1);
strcpy (ptr->name,sym_name);
ptr->offset = data_location();
ptr->next = (struct symrec *)sym_table;
sym_table = ptr;
return ptr;
}
...
*odific!rile parserului 0anali+orului sintactic1/ 6imple&-
Complet!m exemplul nostru anterior cu generarea de cod& Vom extinde defini]iile din fi'
[ierele ;ex [i Bacc ale limba=ului 6imple astfel ca s! gener!m cod pentru 6'ma[in!&
#entru `nceput (om modifica fi]ierele Bacc [i ;ex astfel ca (alorile constantelor s! fie
transmise de la scanner 0anali+orul lexical1 la parser 0anali+orul sintactic1& <l e acel
care$ prin reguli semantice ata[ate regulilor sintactice$ generea+! cod&
Vom modifica defini]ia acelui Isemantic'recordI din fi[ierul Bacc astfel ca (aloarea
constantelor s! fie returnat! ca parte a acestui Isemantic'recordI& Corespun+!toare
celor dou! etic.ete care apar `n codurile instruc]iunilor if [i A.ile (a exista o structur! cu
dou! cmpuri&
6e (a defini [i un tip special de atomi 0ItoHenI1 numit UlblsV corespun+!tor lui 3F [i
TM3;<& <l ofer! [i spa]iu de stocare pentru adresele etic.etelor ce's ad!ugate `n
procesul de bacHpatc.ing& ne)lblrec e func]ia care aloc! spa]iul necesar pentru a
stoca (alorile etic.etelor necesare la bacHpatc.ing&
Func]ia context#ceck (a prelua generarea de cod aferent! opera]iei efectuate asupra
unei (ariabile 0dar (a a(ea ne(oie [i de codul opera]iei de implementat R1& Codul e
generat doar dac! identificatorul exist! `n tabel!&
4:
%{#include <stdio.h> /* Pentru /O */
#include <stdlib.h> /* Pentru malloc folosit aici si in ST.h */
#include <string.h> /* Pentru strcmp folosuit in tabela de simboluri St.h */
#include "ST.h" /* Tabela de Simboluri */
#include "SM.h" /* S-Masina */
#include "CG.h" /* Generator de cod */
#define YYDEBUG 1 /* Pentru depanare */
int errors; /* Contor de erori incrementat de CG.h */
struct lbs /* Pentru etichetele de la if si while */
{
int for_goto;
int for_jmp_false;
};
struct lbs * newlblrec() /* Alloca spatiu pentru etichete */
{
return (struct lbs *) malloc(sizeof(struct lbs));
}
install ( char *sym_name )
{
symrec *s;
s = getsym (sym_name);
if (s == 0)
s = putsym (sym_name);
else { errors++;
printf( "%s is already defined\n", sym_name );
}
}
context_check( enum code_ops operation, char *sym_name )
{ symrec *identifier;
identifier = getsym( sym_name );
if ( identifier == 0 )
{ errors++;
printf( "%s", sym_name );
printf( "%s\n", " is an undeclared identifier" );
}
else gen_code( operation, identifier->offset );
}
%}
%union semrec /* Record-ul semantic */
{
int intval; /* Valoarea cinstantei intregi */
char *id; /* dentificatorul */
struct lbs *lbls /* Adrese etichetate pentru backpatching*/
}
%start program /* Neterminalul de la care incepe analiza e "program" */
%token <intval> NUMBER /* Constante intregi */
%token <id> DENTFER /* dentificatori */
%token <lbls> F WHLE /* Etichete pentru backpatching */
%token SKP THEN ELSE F DO END
%token NTEGER READ WRTE LET N
%token ASSGNOP
%left '-' '+' /* Operatorii asociaza la stinga si au prioritate minima */
%left '*' '/' /* Operatorii asociaza la stinga */
%right '^' /* Operatorii asociaza la dreapta si au prioritatea maxima*/
47
%%
/* Regulile gramaticii si Actiunile semantice */
%%
/* Subrutine scrise in C*/
%nali+orul sintactic$ parserul$ este acum extins cu reguli de generare [i `mbinare a por]
iunilor de cod& 2n final$ codul generat pentru instruc]iunile if [i A.ile trebuie s! con]in!
adresele corecte pentru salturi& %cetsea sunt marcate cu etic.ete$ `n regulile de
traducere& "eoarece destina]iile exacte ale salturilor nu sunt cunoscute dect dup!
generarea codului `ntregii structuri$ e ne(oie de aceast! ad!ugare a lor$ numit! back-
patcing 0ceea ce s'ar putea traduce prin Ipeticire `napoiI1& Valoarea exact! a adresei
destina]ie pentru salturi (a fi ad!ugat! 0ca un petec1 `n cod$ dup! ce$ prin compilarea
`ntregii instruc]iuni structurate se (a [ti precis ce adres! e `n punctul (i+at$
corespun+!tor etic.etei 0fie ea ;1 sau ;21&
Bacc permite pentru fiecare regul! sintactic! s! ad!ug!m ac]iuni semantice care (or
genera cod& *ai mult dec!t att$ pentru fiecare element 0terminal sau neterminal din
regul!1 Bacc asocia+! o (ariabil! special! al c!rui nume `ncepe cu \ [i continu! cu
num!rul elementului din regul!& Capul regulii beneficia+! [i el de o asemenea (ariabil!$
\\$ f!r! num!r& Consulta]i documenta]ia Bacc@Bison de pe sistemul dumnea(oastr!$
pentru a afla am!nunte& #ute]i folosi aceste (ariabile locale procedurilor de anali+!
sintactic! pentru a stoca informa]ii semantice 0atribute1 despre elementul sintactic
respecti(& "ac! a(e]i de stocat mai multe informa]ii pute]i s! folosi]i (ariabila ca pe
adresa unei structuri de date ce (a con]ine informa]iile necesare& 6tructura de date o
(e]i creea `ns! dumnea(oastr! prin alocare dinamic!&
C.iar [i declara]iile de (ariabile 0statice1 (or genera cod/ codul generat de o declara]ie
nu face dect s! re+er(e loc `n segmentul de date pentru (ariabila respecti(!&
/* Declaratiile pentru C si Parser */
%%
program : LET
declarations
N { gen_code( DATA, data_location()-1 ); }
commands
END { gen_code( HALT, 0 ); YYACCEPT; }
;
declarations : /* empty */
| NTEGER id_seq DENTFER '.' { install( $3 ); }
;
id_seq : /* empty */
| id_seq DENTFER ',' { install( $2 ); }
;
3nstruc]iunile 3F [i TM3;< (or recurge la bacHpatc.ing&
commands : /* empty */
| commands command ';'
;
command : SKP
| READ DENTFER { context_check( READ_NT, $2 ); }
| WRTE exp { gen_code( WRTE_NT, 0 ); }
50
| DENTFER ASSGNOP exp { context_check( STORE, $1 ); }
| F exp { $1 = (struct lbs *) newlblrec();
$1->for_jmp_false = reserve_loc(); }
THEN commands { $1->for_goto = reserve_loc(); }
ELSE { back_patch( $1->for_jmp_false,
JMP_FALSE,
gen_label() ); }
commands
F { back_patch( $1->for_goto, GOTO, gen_label() ); }
| WHLE { $1 = (struct lbs *) newlblrec();
$1->for_goto = gen_label(); }
exp { $1->for_jmp_false = reserve_loc(); }
DO
commands
END { gen_code( GOTO, $1->for_goto );
back_patch( $1->for_jmp_false,
JMP_FALSE,
gen_label() ); }
;
Codul corespun+!tor expresiilor e generat de regulile de mai =os/
exp : NUMBER { gen_code( LD_NT, $1 ); }
| DENTFER { context_check( LD_VAR, $1 ); }
| exp '<' exp { gen_code( LT, 0 ); }
| exp '=' exp { gen_code( EQ, 0 ); }
| exp '>' exp { gen_code( GT, 0 ); }
| exp '+' exp { gen_code( ADD, 0 ); }
| exp '-' exp { gen_code( SUB, 0 ); }
| exp '*' exp { gen_code( MULT, 0 ); }
| exp '/' exp { gen_code( DV, 0 ); }
| exp '^' exp { gen_code( PWR, 0 ); }
| '(' exp ')'
;
%%
/* Subprograme C */
*odific!rile %nali+orului ;exical$ 06canerului1
, `ntrebare pe care ('o pune]i citind regulile de compilare a expresiilor [i semn!turile
func]iilor implicate este de ce pentru F>*B<D (aloarea (ariabilei Bacc \1 este c.iar
(aloarea numeric! a constantei iar `n ca+ul unui identificator 03"<F)3F3<D1 este c.iar
stringul format de literele identificatorului& ;a urma urmei de ce n'ar fi [i la num!r la fel
ca la identificator G 6! se transmit! [irul cifrelor$ de ce nu G Ceea ce nu am specificat
este c! acest comportament (a trebui preci+at express `n specifica]iile scanerului&
Valoarea respecti(! (a fi stocat! `n record'ul semantic&
%{
#include <string.h> /* for strdup */
#include "simple.tab.h" /* for token definitions and yylval */
%}
DGT [0-9]
51
D [a-z][a-z0-9]*
%%
{DGT}+ { yylval.intval = atoi( yytext );
return(NT); }
...
{D} { yylval.id = (char *) strdup(yytext);
return(DENT); }
[ \t\n]+ /* eat up whitespace */
. { return(yytext[0]);}
%%
, func]ie pentru afi[area codului
#entru a afi[a codul generat pute]i ad!uga la finalul modulului C9&. urm!toarea func]ie&
%pela]i'o dup! generarea de cod$ `nainte de a'l executa$ pentru a (erifica codul
generat&
, serie de exemple de mici programe `n 6imple [i codul generat la compilarea lor inten'
]ion!m s! le anex!m acestui material&
void _print_code();
{
int i = 0;
while (i < code_offset) {
printf("%3ld: %-10s%4ld\n",i,op_name[(int) code[i].op], code[i].arg );
i++
}
}
>n exemplu
#entru a ilustra felul cum func]ionea+! generatorul de cod al compilatorului nostru
pre+ent!m un program `n 6imple [i codul generat 0Codul a fost pre+entat `n figura 4&2$
la `nceputul capitolului1&
let
integer n,x.
in
read n;
if n < 10 then x := 1; else skip; fi;
while n < 10 do x := 5*x; n := n+1; end;
skip;
write n;
write x;
end
Figura 7.1: Program Simple
52
Capitolul :
,ptimi+area de cod dup! generare
C.iar [i dup! generarea codului exist! optimi+!ri care se mai pot face& Fu uita]i c! por]i'
unile de cod generat s'au al!turat a[a cum impunea sursa programul de compilat dar
nimic nu garantea+! c! `mbinarea lor este optim!& "e asemenea anumite constante
care apar `n instruc]iunile generate pot sugerea `nlocuirea `ntregii instruc]iuni cu alta
mai scurt! sau mai rapid!& >nele `nmul]iri sau `mp!r]iri$ de exemplu cele cu 2 pot fi
`nlocuite cu alte opera]ii$ cum sunt cele de deplasare a bi]ilor& 3nstruc]iuni de adunare
cu +ero $ cele de `nmul]ire cu 1 [i alte opera]ii de(enite inutile din cau+a anumitor (alori
ale constantelor pot fi `nlocuite ori cu F,# 0no operation1 sau c.iar eliminate& %dunarea
sau sc!derea cu 1 beneficia+! [i ele de instruc]iuni speciale mai rapide$ pe care
ma=oritatea procesoarelor .ardAare le ofer!& 3ar anumite opera]ii cu (ariabile pot fi
`nlocuite cu opera]ii reali+ate cu a=utorul regi[trilor procesorului$ m!rindu'se astfel (ite+a
codului generat&
#entru a'l optimi+a$ `ntregul cod generat (a fi parcurs a(nd la fiecare moment `n (i+or
cte(a instruc]iuni (ecine 0ca [i cum a]i (edea o camer! pri(ind pe gaura c.eii1& "ac!
ele se potri(esc cu anumite [abloane cunoscute de optimi+ator 0 procesul e numit c.iar
Ipeep.ole optimi+ationI ' Ioptimi+are tip gaura c.eiiI1 atunci acesta le (a `nlocui cu alte
sec(en]e de cod mai rapide 0sau mai eficiente din alt punct de (edere$ de exemplu mai
scurte1& >n exemplu tipic este eliminarea unor sec(en]e #>6M E #,# care nu fac dect
s! pun! [i s! scoat! aceea[i (aloare din sti(! sau inlocuirea acestora cu opera]ii de
transfer `ntre registri 0dac! sunt mai mul]i cu func]ii asem!n!toare1 sau `ntre regi[tri [i
memorie&
Fu (om ilustra `n exemplul nostru de compilare a limba=ului 6imple asemenea te.nici
de optimi+are& "e altfel limba=ul ma[in! extrem de simplu al 6'ma[inii noastre nu ofer!
prea multe posibilita]i de a face asemenea optimi+!ri$ fiind un limba= minimalist& Cu totul
alta este situa]ia atunci cnd se generea+! cod pentru un procesor .ardAare real$ care
este oferit de fabricant cu un set mult mai (ast de instruc]iuni$ dintre care unele pot
`nlocui uneori cu suces pe altele$ oferind [i a(anta=e&
55
Capitolul 7
;ecturi suplimentare
2n ultimele (ersiuni 015 sept& 2005 [i 25 feb& 20041 ale documentului care a stat la ba+a
acestui (olum$ document oferit de prof& %nt.on- %& %ab- prin 3nternet capitolul 7 nu
cuprindea dect dou! rnduri care recomand! alte materiale ' nenumite ' pri(ind ;ex [i
Bacc precum [i lucr!rile ' tot necitate ' scrise de un autor pe nume #ratt$ pri(itoare la
ma[inile (irtuale& Vom suplini aceast! omisiune indicnd alte materiale accesibile `n
Domnia sau pe 3nternet pe care le'am selectat `n procesul elabor!rii acestui (olum
deri(at din lucrarea domnului %nt.on- %& %ab-&
"espre 6&,& >F3N [i componentele sale$ inclu+nd Bacc [i ;ex pute]i consulta capitolul
11 al (olumui de mai =os$ scris de Valentin Cristea [i colecti(ul s!u de coautori& <xplica'
]ii suplimentare despre folosirea (ariabilelor \\ [i \1$\2 `n regulile semantice se g!sesc
la pagina 254&
4) 5alentin (ristea, %lexandru 2\noiu, 'ugenia 6alis), 0rina %t#anasiu, 7orina
8egreanu, Silviu (\linoiu, 3lorin 9aboescu - UNIX, 9ucure[ti 4::;, 'd."eora ,
0S98 :<;-=>4-4>?-@
, carte accesibil!$ disponibil! [i prin 3nternet dup! ce `n prealabil fusese publicat! de
3nternational ).omson `n 1778 apar]ine profesorului #&"&)err- de la D.odes >ni(ersit-&
2n anex! este un `ntreg compilator pentru limba=ul Clang$ scris `n C& <xtrem de
instructi(!& ,fer! un bun suport teoretic dar recomand! alt generator de compilatoare$
Coco@D& 6e poate g!si c!utnd numele profesorului )err- cu un motor de c!utare& 2n
prefa]a c!r]ii sunt indicate site'urile/ .ttp/@@AAA&scifac&ru&ac&+a@compilers@ [i
.ttp/@@cs&ru&ac&+a@.ome@cspt@compbooH&.tm&
A) 2.,."erry, Compilers and Compiler Generators, 1#odes .niversity, 4::=,
2ublis#ed by 0nternational "#omson
>rmea+! un concis dar frumos manual de folosire pentru ;ex [i Bacc$ utili+abil cu pu]in
effort [i pentru clonele lor de pe platforma ;inux$ Flex'ul [i Bison'ul& <ra disponibil `n
format pdf pe site'ul epapers&com& Compilatorul pre+entat acolo foloseste un arbore
creat explicit nu implicit ca `n exemplul din acest (olum& %cest arbore poate fi exploatat
de un e(aluator$ interpretor'ul de arbori$ ob]in`ndu'se un interpretor pentru limba=ul
propus& %lt! (ariant! este generarea de cod pe ba+a arborelui& >n exerci]iu interesant
este implementarea unui compilator ca cel din lucrarea amintit! 0mai =os1 folosind o
distribu]ie ;inux care include programele Flex [i Bison&
;) "#omas 8iemann, A Compact Guide to Lex & Yacc, epapers.com
#entru cunosc!torii de #ascal interesa]i s! scrie f!r! generator un mic compilator putem
54
recomanda un (olum practic$ de tipul Ilearn'b-'doingI scris de un specialist `n fi+ic! dar
pasionat de compilatoare$ domnul WacH T&Crens.aA& <xist! di(erse (ersiuni pe 3nternet
ale serialului s!u despre scrieirea practic! a unui compilator$ fie ca ar.i(e +ip cu plain'
text sau ca fi[ier pdf& %m a(ut la dispo+i]ie (ersiunea 1&: `n format pdf& < un mod
interesant de a face cuno[tin]! cu un compilator [i cu problemele reali+!rii acestuia&
#unctul de (edere este cel al practicianului care nu'[i pierde mult timp cu teoria& Ceea
ce face ca lectura unui (olum de teorie `npreun! cu acesta s! fie cu att mai
interesant!&
@) Bac$ C. (rens#aD, Compiler Building Tutorial, ver. 4.E, %prill 44,A>>4.
2n cele din urm!$ dar poate cel mai citat$ celebrul (olum scris de %lfred %.o$ Da(i 6et.i
[i Weffre- >llmann `n 17:8 [i republicat apoi `n 17::& 6e poate g!si la unele biblioteci
din Domnia&
?) %lfred %#o, 1avi Set#i [i Beffrey .llmann, (ompilers, 2rinciples, "ec#niFues
and "ools, 4:E=, %ddison-Cesley, 1eading, Gassac#usetts.

55
Capitolul 10
<xerci]ii
<xerci]iile care urmea+! sunt (ariate ca dificultate& #entru fiecare se cere s! determina]i
ce modific!ri trebuie f!cute gramaticii$ tabelei de simboluri [i ma[inii cu sti(!& 6unt
cte(a dintre exerci]iile oferite de prof& %&%&%ab- ele(ilor s!i&
1& De'implementa]i tabela de simboluri sub form! de arbore binar de c!utare&
2& De'implementa]i tabela de simboluri ca tabel! .as.&
5& De'implementa]i tabela de simboluri$ generatorul de cod [i ma[ina cu sti(! sub form!
de clase C++.0Foile (ersiuni de Flex [i Bison pot produce [i ele cod sub form! de clase
C++.1
4& <xtinde]i compilatorul cu extensiile date mai =os& <xtensiile cer modificarea scanerului
pentru a manipula noii atomi [i modificarea parserului pentru a gestiona gramatica
extins!&
0a1 "eclara]ii/ 6c.imba]i procesarea semanticii identificatorilor astfel `nct ace[tia
s! 0nu1 necesite declarare anterioar!&
0b1 Constante [i (ariabile reale/ <xtinde]i tabela de simboluri astfel `nct
subrutinele care'o actuali+ea+! s! stoc.e+e [i atributul de tip pentru fiecare
identificator& <xtinde]i rutinele semantice ale generatorului de cod astfel ca acesta s!
genere+e codul corespun+!tor tipului de constante [i (ariabile pe care le `ntlne[te$
(ariabile pe care aceste rutine le primesc ca parametri&
0c1 2nmul]ire$ `mp!r]ire 0[i ridicare la putere R1& Face]i sc.imb!rile necesare `n
rutinele semantice pentru a se ocupa corect de generarea de cod&
0d1 3nstruc]iunile if [i D#ile+ Dutinele semantice trebuie s! genere+e propriile
teste [i salturi&
0e1 #roceduri f!r! parametri/ )abela de simboluri trebuie extins! pentru a
manipula declara]ii imbricate iar rutinele semantice trebuie extinse pentru a genera cod
pentru asigurarea transferului controlului la fiecare punct de apel [i de asemenea la
`nceputul [i sfr[itul corpului procedurii& 3ndica]ie/ 6e (a folosi registrul %D al ma[inii
(irtuale [i instruc]iunile care operea+! cu el&
,p]ional pute]i ad!uga/
0a1 >n interpretor pentru codul produs de compilator&
0b1 2nlocui]i parserul g.idat de tabele$ cu un parser descendent recursi(&
5& <xtinde]i compilatorul& , descriere este 0sau a fost1 inclus! `n dosarul cs580@compiler
tools de pe site'ul cs&AAc&edu& #e scurt$ sunt cerute urm!toarele extensii/
58
0a1 <xtinderea scanerului pentru a manipula noii atomi& Folosi]i un generator
pentru a produce noile tabele&
0b1 "eclara]ii pentru (ariabile `ntregi [i reale&
0c1 Constante `ntregi$ expresii cu `ntregi$ opera]ii de 3@, pentru `ntregi [i de ie[ire
pentru stringuri&
0d1 3nstruc]iunea loop cu exit [i ad!ugarea lui else [i elsif la instruc]iunea if.
0e1 #roceduri recursi(e cu parametri&
0f1 "eclararea recordurilor [i utili+area cmpurilor&
0g1 "eclararea (ectorilor [i utili+area elementelor din (ectori&
0.1 >tili+area modulelor [i folosirea identificatorilor cu calificare&
8& Compilatorul urm!tor trebuie s!'l scrie]i complet$ de la +ero& ;ista de mai =os enumer!
caracteristicile limba=ului$ pre+entnd `nti un subset de ba+! absolut necesar& Celelalte
caracteristici care urmea+! sunt op]ionale&
6etul de ba+!/
0a1 )ipurile `ntreg$ real$ boolean&
0b1 <xpresii simple cu `ntregi reali [i (alori booleene folosind operatorii/ +6- 6*6 36
/o&6 a/!6 or6 abs6 +o!6 **6 767#6868#6#6 3#
0c1 ,pera]ii de intrare pentru (alori `ntregi$ reale [i booleene
0d1 ,pera]ii de ie[ire pentru stringuri [i expresii `ntregi$ reali$ (alori booleene&
F!r! formatare&
0e1 6tructuri de bloc$ inclu+nd declara]ii de (ariabile locale [i de constante
0f1 %tribuirea
0g1 3nstruc]iunile if$ loop [i exit
0.1 #roceduri [i func]ii f!r! argumente$ cu re+ultat scalar$ inclusi( imbricate [i cu
(ariabile non'locale&
6etul op]ional/
Fu este tradus aici& 2l pute]i g!si `n lucrarea original! a prof& %&%&%ab-&
Deamintim c! un compilator scris de la +ero dar care generea+! cod pentru un procesor
real *otorola g!si]i `n (olumul lui Bac$ C. (rens#aD, Compiler Building Tutorial,
ver. 4.E, %prill 44,A>>4, disponibil pe 3nternet&
54
%nexa %
;imba=ul 6imple ' 3mplementarea complet!
%1& #arserul 6imple&-
"ac! a]i reali+at fi[ierul cu specifica]ii Bacc@Bison$ conform cu indica]iile din capitolele
precedente$ ar trebui s! ob]ine]i un text similar cu cel de mai =os$ cu excep]ia
comentariilor& "ecomentnd rndul /*yydebug = 1;*/ din func]ia main (e]i ob]ine la
execu]ie mult mai multe detali despre func]ionarea parserului&
%{/*************************************************************************
Compiler for the Simple language
***************************************************************************/
/*=========================================================================
C Libraries, Symbol Table, Code enerator ! other C "ode
=========================================================================*/
#in"lude $stdio%h& /* 'or (/) */
#in"lude $stdlib%h& /* 'or mallo" here and in symbol table */
#in"lude $string%h& /* 'or str"mp in symbol table */
#in"lude *ST%h* /* Symbol Table */
#in"lude *S+%h* /* Sta", +a"hine */
#in"lude *C%h* /* Code enerator */
#define --./01 1 /* 'or .ebugging */
int errors; /* /rror Count */
/*2222222222222222222222222222222222222222222222222222222222222222222222222
The follo3ing support ba",pat"hing
2222222222222222222222222222222222222222222222222222222222222222222222222*/
stru"t lbs /* Labels for data, if and 3hile */
{
int for4goto;
int for45mp4false;
6;
stru"t lbs * ne3lblre"78 /* 9llo"ate spa"e for the labels */
{
return 7stru"t lbs *8 mallo"7si:eof7stru"t lbs88;
6
/*2222222222222222222222222222222222222222222222222222222222222222222222222
(nstall identifier ! "he", if pre;iously defined%
2222222222222222222222222222222222222222222222222222222222222222222222222*/
install 7 "har *sym4name 8
{
symre" *s;
s = getsym 7sym4name8;
if 7s == <8
s = putsym 7sym4name8;
else { errors==;
printf7 *%s is already defined>n*, sym4name 8;
6
6
/*2222222222222222222222222222222222222222222222222222222222222222222222222
(f identifier is defined, generate "ode
2222222222222222222222222222222222222222222222222222222222222222222222222*/
"onte?t4"he",7 enum "ode4ops operation, "har *sym4name 8
{ symre" *identifier;
identifier = getsym7 sym4name 8;
5:
if 7 identifier == < 8
{ errors==;
printf7 *%s*, sym4name 8;
printf7 *%s>n*, * is an unde"lared identifier* 8;
6
else gen4"ode7 operation, identifier2&offset 8;
6
/*=========================================================================
S/+9@T(C A/C)A.S
=========================================================================*/
%6
%union semre" /* The Semanti" Ae"ords */
{
int int;al; /* (nteger ;alues */
"har *id; /* (dentifiers */
stru"t lbs *lbls; /* 'or ba",pat"hing */
6
/*=========================================================================
T)B/@S
=========================================================================*/
%start program
%to,en $int;al& @1+0/A /* Simple integer */
%to,en $id& (./@T('(/A /* Simple identifier */
%to,en $lbls& (' CD(L/ /* 'or ba",pat"hing labels */
%to,en SB(E TD/@ /LS/ '( .) /@.
%to,en (@T//A A/9. CA(T/ L/T (@
%to,en 9SS@)E
/*=========================================================================
)E/A9T)A EA/C/./@C/
=========================================================================*/
%left F2F F=F
%left F*F F/F
%right FGF
/*=========================================================================
A9++9A A1L/S for the Simple language
=========================================================================*/
%%
program H L/T
de"larations
(@ { gen4"ode7 .9T9, data4lo"ation78 2 1 8; 6
"ommands
/@. { gen4"ode7 D9LT, < 8; --9CC/ET; 6
;
de"larations H /* empty */
I (@T//A id4seJ (./@T('(/A K%K { install7 LM 8; 6
;
id4seJ H /* empty */
I id4seJ (./@T('(/A F,F { install7 LN 8; 6
;
"ommands H /* empty */
I "ommands "ommand F;F
;
"ommand H SB(E
I A/9. (./@T('(/A { "onte?t4"he",7 A/9.4(@T, LN 8; 6
I CA(T/ e?p { gen4"ode7 CA(T/4(@T, < 8; 6
I (./@T('(/A 9SS@)E e?p { "onte?t4"he",7 ST)A/, L1 8; 6
I (' e?p { L1 = 7stru"t lbs *8 ne3lblre"78;
L12&for45mp4false = reser;e4lo"78; 6
57
TD/@ "ommands { L12&for4goto = reser;e4lo"78; 6
/LS/ { ba",4pat"h7 L12&for45mp4false,
O+E4'9LS/,
gen4label78 8; 6
"ommands
'( { ba",4pat"h7 L12&for4goto, )T), gen4label78 8; 6
I CD(L/ { L1 = 7stru"t lbs *8 ne3lblre"78;
L12&for4goto = gen4label78; 6
e?p { L12&for45mp4false = reser;e4lo"78; 6
.)
"ommands
/@. { gen4"ode7 )T), L12&for4goto 8;
ba",4pat"h7 L12&for45mp4false,
O+E4'9LS/,
gen4label78 8; 6
;
e?p H @1+0/A { gen4"ode7 L.4(@T, L1 8; 6
I (./@T('(/A { "onte?t4"he",7 L.4P9A, L1 8; 6
I e?p F$F e?p { gen4"ode7 LT, < 8; 6
I e?p F=F e?p { gen4"ode7 /Q, < 8; 6
I e?p F&F e?p { gen4"ode7 T, < 8; 6
I e?p F=F e?p { gen4"ode7 9.., < 8; 6
I e?p F2F e?p { gen4"ode7 S10, < 8; 6
I e?p F*F e?p { gen4"ode7 +1LT, < 8; 6
I e?p F/F e?p { gen4"ode7 .(P, < 8; 6
I e?p FGF e?p { gen4"ode7 ECA, < 8; 6
I F7F e?p F8F
;
%%
/*=========================================================================
+9(@
=========================================================================*/
main7 int arg", "har *arg;RS 8
{ e?tern '(L/ *yyin;
==arg;; 22arg";
yyin = fopen7 arg;R<S, *r* 8;
/*yydebug = 1;*/
errors = <;
yyparse 78;
printf 7 *Earse Completed>n* 8;
if 7 errors == < 8
{ print4"ode 78;
fet"h4e?e"ute4"y"le78;
6
6
/*=========================================================================
--/AA)A
=========================================================================*/
yyerror 7 "har *s 8 /* Called by yyparse on error */
{
errors==;
printf 7*%s>n*, s8;
6
/**************************** /nd rammar 'ile ***************************/
80
%&2& 3ndica]ii de lucru
%m transcris mai =os comen+ile pe care (a trebui s! le da]i sistemului dumnea(oastr!
;inux& %m testat aceast! sec(en]! pe un DedMat ;inux 5&2 [i nu am g!sit deosebiri fa]!
de comen+ile propuse de dl& %&%&%ab-& 6ingurele deosebiri au fost c! promptul
sistemului meu ;inux nu este IVI ci I\I 0de[i el se poate modifica folosind comanad
prompt1 iar (ersiunea de compilator gcc folosit! mai a(ea ne(oie de o op]iune `n linia de
comand! 0 'lfl1&
> bison -d Simple.y
sau
> bison -dv Simple.y
Simple.y contains 39 shift/reduce conflicts.
> gcc -c Simple.tab.c
> flex Simple.lex
> gcc -c lex.yy.c
> gcc -o Simple Simple.tab.o lex.yy.o -lm -lfl
> Simple test_simple
Parse Completed
0: data 1
1: in_int 0
2: ld_var 0
3: ld_int 10
4: lt 0
5: jmp_false 9
6: ld_int 1
7: store 1
8: goto 9
9: ld_var 0
10: ld_int 10
11: lt 0
12: jmp_false 22
13: ld_int 5
14: ld_var 1
15: mult 0
16: store 1
17: ld_var 0
18: ld_int 1
19: add 0
20: store 0
21: goto 9
22: ld_var 0
23: out_int 0
24: ld_var 1
25: out_int 0
26: halt 0
81
%&5& 6canerul/ 6imple&lex
/***************************************************************************
S"anner for the Simple language
***************************************************************************/
%{
/*=========================================================================
C2libraries and To,en definitions
=========================================================================*/
#in"lude $string%h& /* for strdup */
/*#in"lude $stdlib%h& */ /* for atoi */
#in"lude *Simple%tab%h* /* for to,en definitions and yyl;al */
%6
/*=========================================================================
T)B/@ .efinitions
=========================================================================*/
.((T R<2TS
(. Ra2:SRa2:<2TS*
/*=========================================================================
A/1L9A /UEA/SS()@S defining the to,ens for the Simple language
=========================================================================*/
%%
*H=* { return79SS@)E8; 6
{.((T6= { yyl;al%int;al = atoi7 yyte?t 8;
return7@1+0/A8; 6
do { return7.)8; 6
else { return7/LS/8; 6
end { return7/@.8; 6
fi { return7'(8; 6
if { return7('8; 6
in { return7(@8; 6
integer { return7(@T//A8; 6
let { return7L/T8; 6
read { return7A/9.8; 6
s,ip { return7SB(E8; 6
then { return7TD/@8; 6
3hile { return7CD(L/8; 6
3rite { return7CA(T/8; 6
{(.6 { yyl;al%id = 7"har *8 strdup7yyte?t8;
return7(./@T('(/A8; 6
R >t>nS= /* eat up 3hitespa"e */
% { return7yyte?tR<S8; 6
%%
int yy3rap7;oid8{6
/************************** /nd S"anner 'ile *****************************/
82
%&4 )abela de simboluri/ 6t&.
/***************************************************************************
Symbol Table +odule
***************************************************************************/
/*=========================================================================
./CL9A9T()@S
=========================================================================*/
/*2222222222222222222222222222222222222222222222222222222222222222222222222
S-+0)L T90L/ A/C)A.
2222222222222222222222222222222222222222222222222222222222222222222222222*/
stru"t symre"
{
"har *name; /* name of symbol */
int offset; /* data offset */
stru"t symre" *ne?t; /* lin, field */
6;
typedef stru"t symre" symre";
/*2222222222222222222222222222222222222222222222222222222222222222222222222
S-+0)L T90L/ /@TA-
2222222222222222222222222222222222222222222222222222222222222222222222222*/
symre" *identifier;
/*2222222222222222222222222222222222222222222222222222222222222222222222222
S-+0)L T90L/
(mplementationH a "hain of re"ords%
222222222222222222222222222222222222222222222222222222222222222222222222*/
symre" *sym4table = 7symre" *8<; /* The pointer to the Symbol Table */
/*========================================================================
)perationsH Eutsym, etsym
========================================================================*/
symre" * putsym 78;
symre" * getsym 78;
symre" * putsym 7"har *sym4name8
{
symre" *ptr;
ptr = 7symre" *8 mallo" 7si:eof7symre"88;
ptr2&name = 7"har *8 mallo" 7strlen7sym4name8=18;
str"py 7ptr2&name,sym4name8;
ptr2&offset = data4lo"ation78;
ptr2&ne?t = 7stru"t symre" *8sym4table;
sym4table = ptr;
return ptr;
6
symre" * getsym 7"har *sym4name8
{
symre" *ptr;
for 7 ptr = sym4table;
ptr V= 7symre" *8 <;
ptr = 7symre" *8ptr2&ne?t 8
if 7str"mp 7ptr2&name,sym4name8 == <8
return ptr;
return <;
6
/************************** /nd Symbol Table **************************/
85
%&5 9eneratorul de cod/ C9&.
/***************************************************************************
Code enerator
***************************************************************************/
/*2222222222222222222222222222222222222222222222222222222222222222222222222
.ata Segment
2222222222222222222222222222222222222222222222222222222222222222222222222*/
int data4offset = <; /* (nitial offset */
int data4lo"ation78 /* Aeser;es a data lo"ation */
{
return data4offset==;
6
/*2222222222222222222222222222222222222222222222222222222222222222222222222
Code Segment
2222222222222222222222222222222222222222222222222222222222222222222222222*/
int "ode4offset = <; /* (nitial offset */
int reser;e4lo"78 /* Aeser;es a "ode lo"ation */
{
return "ode4offset==;
6
int gen4label78 /* Aeturns "urrent offset */
{
return "ode4offset;
6
/* enerates "ode at "urrent lo"ation */
;oid gen4"ode7 enum "ode4ops operation, int arg 8
{
"odeR"ode4offsetS%op = operation;
"odeR"ode4offset==S%arg = arg;
6
/* enerates "ode at a reser;ed lo"ation */
;oid ba",4pat"h7 int addr, enum "ode4ops operation, int arg 8
{
"odeRaddrS%op = operation;
"odeRaddrS%arg = arg;
6
/*2222222222222222222222222222222222222222222222222222222222222222222222222
Erint Code to stdio
2222222222222222222222222222222222222222222222222222222222222222222222222*/
;oid print4"ode78
{
int i = <;
3hile 7i $ "ode4offset8 {
printf7*%MldH %21<s%Wld>n*,i,op4nameR7int8 "odeRiS%opS, "odeRiS%arg 8;
i==;
6
6
/************************** /nd Code enerator **************************/
84
%&8 *a[ina cu sti(! / 6*&.
/***************************************************************************
Sta", +a"hine
***************************************************************************/
/*=========================================================================
./CL9A9T()@S
=========================================================================*/
/* )E/A9T()@SH (nternal Aepresentation */
enum "ode4ops { D9LT, ST)A/, O+E4'9LS/, )T),
.9T9, L.4(@T, L.4P9A,
A/9.4(@T, CA(T/4(@T,
LT, /Q, T, 9.., S10, +1LT, .(P, ECA 6;
/* )E/A9T()@SH /?ternal Aepresentation */
"har *op4nameRS = { *halt*, *store*, *5mp4false*, *goto*,
*data*, *ld4int*, *ld4;ar*,
*in4int*, *out4int*,
*lt*, *eJ*, *gt*, *add*, *sub*, *mult*, *di;*,
*p3r* 6;
stru"t instru"tion
{
enum "ode4ops op;
int arg;
6;
/* C)./ 9rray */
stru"t instru"tion "odeRTTTS;
/* A1@2T(+/ Sta", */
int sta",RTTTS;
/*2222222222222222222222222222222222222222222222222222222222222222222222222
Aegisters
2222222222222222222222222222222222222222222222222222222222222222222222222*/
int p" = <;
stru"t instru"tion ir;
int ar = <;
int top = <;
"har "h;
/*=========================================================================
'et"h /?e"ute Cy"le
=========================================================================*/
;oid fet"h4e?e"ute4"y"le78
{ do { /*printf7 *EC = %Md (A%arg = %Xd 9A = %Md Top = %Md,%Xd>n*,
p", ir%arg, ar, top, sta",RtopS8; */
/* 'et"h */
ir = "odeRp"==S;
/* /?e"ute */
s3it"h 7ir%op8 {
"ase D9LT H printf7 *halt>n* 8; brea,;
"ase A/9.4(@T H printf7 *(nputH * 8;
s"anf7 *%ld*, !sta",Rar=ir%argS 8; brea,;
85
"ase CA(T/4(@T H printf7 *)utputH %d>n*, sta",Rtop22S 8; brea,;
"ase ST)A/ H sta",Rir%argS = sta",Rtop22S; brea,;
"ase O+E4'9LS/ H if 7 sta",Rtop22S == < 8
p" = ir%arg;
brea,;
"ase )T) H p" = ir%arg; brea,;
"ase .9T9 H top = top = ir%arg; brea,;
"ase L.4(@T H sta",R==topS = ir%arg; brea,;
"ase L.4P9A H sta",R==topS = sta",Rar=ir%argS; brea,;
"ase LT H if 7 sta",Rtop21S $ sta",RtopS 8
sta",R22topS = 1;
else sta",R22topS = <;
brea,;
"ase /Q H if 7 sta",Rtop21S == sta",RtopS 8
sta",R22topS = 1;
else sta",R22topS = <;
brea,;
"ase T H if 7 sta",Rtop21S & sta",RtopS 8
sta",R22topS = 1;
else sta",R22topS = <;
brea,;
"ase 9.. H sta",Rtop21S = sta",Rtop21S = sta",RtopS;
top22;
brea,;
"ase S10 H sta",Rtop21S = sta",Rtop21S 2 sta",RtopS;
top22;
brea,;
"ase +1LT H sta",Rtop21S = sta",Rtop21S * sta",RtopS;
top22;
brea,;
"ase .(P H sta",Rtop21S = sta",Rtop21S / sta",RtopS;
top22;
brea,;
case PWR : stack[top-1] = stack[top-1] * stack[top];
top--;
break;
default H printf7 *%s(nternal /rrorH +emory .ump>n* 8;
brea,;
6
6
3hile 7ir%op V= D9LT8;
6
/*************************** /nd Sta", +a"hine **************************/
%[a cum am preci+at `n capitolele precedente$ instruc]iunea #TD a ma[inii (irtuale
trebuie s! fac! ridicare la putere nu `nmul]ire& #or]iunea din text care trebuie `nlocuit!
este e(iden]iat!&
88
%&4 >n exemplu de program/ test?simple
let
integer n,x.
in
read n;
if n < 10 then x := 1; else skip; fi;
while n < 10 do x := 5*x; n := n+1; end;
skip;
write n;
write x;
end
Qi codul produs$ de data aceasta al!turate/
0: data 1
1: in_int 0
2: ld_var 0
3: ld_int 10
4: lt 0
5: jmp_false 9
6: ld_int 1
7: store 1
8: goto 9
9: ld_var 0
10: ld_int 10
11: lt 0
12: jmp_false 22
13: ld_int 5
14: ld_var 1
15: mult 0
16: store 1
17: ld_var 0
18: ld_int 1
19: add 0
20: store 0
21: goto 9
22: ld_var 0
23: out_int 0
24: ld_var 1
25: out_int 0
26: halt 0
Figura 7.2: Codul generat
84
Construc]ia compilatoarelor folosind Flex [i Bison
Volumul se adresea+! att programatorilor pe platforma >F3N @ ;3F>N care doresc s!
se instruiasc! `n construc]ia limba=elor de programare ct [i liceenilor [i studen]ilor care
(or s! cunoasc! modul cum se scrie un compilator folosind limba=ul C [i generatoarele
de programe Bacc [i ;ex sau clonele lor Flex [i Bison disponibile pe sistemele de
operare din familia ;inux& #re+entarea pas cu pas a componentelor compilatorului unui
limba= asem!n!tor cu C$ numit 6imple$ `mpreun! cu explicarea clar! a conceptelor
folosite de autori la construc]ia limba=elor de programare [i subsistemelor unui
compilator fac din aceast! carte deopotri(! un curs condensat de compilatoare ct [i un
`ndrumar practic pentru reali+area unui compilator cu aceste instrumente celebre/ Flex
[i Bison&
Volumul poate fi folosit ca material de studiu auxiliar ori ca `ndrumar de laborator `n
cadrul cursului de translatoare sau compilatoare att `n mediul polite.nic ct [i `n
facult!]ile de informatic!&
*u pot s\ v\ descriu emo]ia scrierii primului progr\mel care va rula pe interpretorul
dumneavoastr\ sau va !i compilat cu compilatorul dumneavoastr\. +i mai ales
satis!ac]ia care o ve]i sim]i v\z,nd c\ ruleaz\ sau se compileaz\ "i se execut\ !\r\ erori.
--o spune un !ost absolvent al primei serii de la o !acultate de .n!ormatic\ serie
n\scut\ prin trans!ormarea uneia din cele de la sec]iile 0aculta]ii de 1atematic\.
2an 3opa
Categoria/ Construc]ia compilatoarelor
36BF 745'0'04015'5
8: