Sunteți pe pagina 1din 38

Limbaje formale i translatoare (Compilatoare)

Compilator este numit programul sau setul de programe care


traduce propoziii scrise ntr-un limbaj (limbajul surs) ntr-un alt
limbaj (limbajul int).
Textul iniial se numete cod surs, iar ieirea compilatorului se
numete cod obiect.
Motivul cel mai des ntlnit pentru care este nevoie de traducerea
codului surs const n nevoia de a crea un program executabil.
Numele de compilator se folosete n special pentru programele care
traduc cod surs scris ntr-un limbaj de programare de nivel nalt, n
cod obiect ntr-un limbaj de nivel sczut (limbaj de programare sau
limbaj main).

Cod sursa

Translator

Cod obiect

Programul care poate s traduc dintr-un


limbaj de nivel sczut ntr-un limbaj de nivel
nalt se numete decompilator (decompiler).
Un program capabil s fac traduceri ntre
dou limbaje de programare de nivel nalt se
numete translator de limbaje, translator
surs la surs sau convertor de limbaje.
Programele care pot schimba forma de
exprimare a codului surs, fr a schimba
limbajul n care a fost scris, se numesc
rescriitorare de limbaj (rewriter).

Dup platforma int (platforma pe care va fi executat codul


obiect produs de ctre compilator):
1. Compilatoare native (native/hosted compilers): codul obiect va
fi rulat pe acelai tip de calculator i pe acelai tip de sistem de
operare ca i cele pe care a fost rulat compilatorul
Ex: compilatoarele din BorlandC, Microsoft Visual Studio 6.0
2. Cross compiler: codul obiect generat de ctre compilator va fi
rulat pe un alt tip de platform. Acest tip de compilatoare se
utilizeaz n special pentru dezvoltarea de programe pentru
sistemele embedded, care nu au fost proiectate astfel nct s
suporte un mediu de dezvoltare.
Ex: programele pentru microprocesoare
!. Ieirea compilatorului care produce cod obiect pentru o main
virtual poate fi executat att pe acelai tip de platform ca i
cea pe care a rulat compilatorul, ct i pe un alt tip. De aceea,
aceste compilatoare nu sunt clasificate ca i native sau cross.

Codul surs (secven


de caractere)

Analiza lexical
secven de atomi lexicali
Analiza sintactic
Analiza semantic

Translatare n cod
intermediar
Program n cod intermediar neoptimizat
Optimizarea codului
intermediar
Program n cod intermediar optimizat

Opiune 1:
Generarea de cod:
Codul intermediar -> cod
main sau limbaj de
asamblare
Program n cod main sau limbaj
de asamblare

Opiune 2:
Interpretare:
Simularea execuiei codului
intermediar de ctre un
interpretor
6

Propoziia este valid din


Propoziia este valid din
punct de vedere lexical?
punct de vedere sintactic?
(atomii lexicali care compun
(atomii lexicali sunt n ordinea
propoziia aparin
corect?)
vocabularului limbajului?)

Eminescu este un
sriicotr.
Eminescu scriitor un
este.
Scriitor este un
Eminescu.
Eminescu este un
scriitor.

Propoziia este valid din


punct de vedere semantic?
(Propoziia are neles?)

NU

DA

NU

DA

DA

NU

DA

DA

DA

Un compilator care traduce un limbaj relativ simplu i este


scris de ctre o singur persoan, poate s fie un program
monolitic.
Dac limbajul de nivel nalt care trebuie tradus este mare i
complex, iar calitatea codului obiect generat trebuie s fie
maxim, compilatorul poate fi mprit n mai multe faze
relativ independente (mai multe treceri).
mprirea n faze nseamn c dezvoltarea compilatorului
poate fi mprit la mai multe persoane care lucreaz n
acelai timp.
n plus, este mult mai uor s se nlocuiasc o faz cu o
implementare mai bun, sau s se adauge ulterior alte faze.
mprirea procesului de compilare n faze (treceri) a fost
subiectul unui concurs lansat de Production Quality
Compiler-Compiler Project (PQCC) al universitii Carnegie
Mellon.

10

Acest proiect a dus la introducerea termenilor de


front-end (partea din fa a unui compilator) i
back-end (partea din spate).
Componenta
front-end
este
considerat
responsabil
cu
prelucrarea
sintactic
i
semantic, precum i cu translatarea ntr-o
reprezentare de nivel mai sczut dect cel al
limbajului n care a fost scris codul surs.
Componenta back-end se ocup cu analize,
transformri i optimizri specifice pentru o
numit platform. Apoi ea genereaz cod pentru
un anumit sistem de operare i pentru un anumit
procesor.

11

Analizeaz codul surs cu scopul de a construi o


reprezentare intern a acestuia, numit reprezentare
intermediar.
Creaz i gestioneaz tabela de simboli, o structur de
date care memoreaz pentru fiecare atom lexical din codul
surs informaiile asociate necesare, cum ar fi locaia, tipul
i domeniul de valabilitate.
Toate aceste operaii se realizeaz n mai multe etape:
1. reconstruirea liniilor
2. analiza lexical
3. preprocesarea
4. analiza sintactic
5. analiza semantic
6. generarea codului intermediar

12

Este necesar n cazul limbajelor n care cuvintele cheie sunt


marcate prin simboli speciali (stropping), sau n care se permite
prezena n cadrul identificatorilor a unui numr arbitrar de spaii.

stropping refers to the method used to mark letter sequences as


having a special property (most often being a keyword or certain
type of variable/storage location) wikipedia
Ex: n limbajul Algol68 cuvintele cheie sunt marcate prin prefixarea
cu un apostrof: BEGIN
n limbajul Algol60 cuvintele cheie sunt marcate prin scrierea lor
ntre apostrofi: BEGIN
Limbajele Ruby i Pearl utilizeaz caracterere sigil pentru a
identifica caracteristicile unei variabile/constante
Avantajul utilizrii stropping este posibilitatea de a utiliza aceeai
secven de caractere pentru a reprezenta atomi lexicali cu
semnificaie diferit.
Ex: slide-ul urmtor
Reconstruirea liniilor pregtete codul surs pentru analiza
gramatical, convertind secvena de caractere ntr-o form canonic.

13

In the PHP language, which was largely inspired by Perl, $ precedes any variable name.
Names not prefixed by this are considered constants or functions.
In Ruby, ordinary variables lack sigils, but $ is prefixed to global variables, @ is
prefixed to instance variables, and @@ is prefixed to class variables (the second @
cannot be considered a twigil, so @@ is just a longer sigil).
In Windows PowerShell, which was partly inspired by Unix shells and Perl, variable names
are prefixed by the $ sigil.
In Transact-SQL, @ precedes a local variable or parameter name. System variables
(known as global variables) are distinguished by a @@ prefix.
In mIRC script, identifiers have a $ sigil, while all variables have a % prefixed (regardless
of local or global variables or data type). Binary variables are prefixed by an &.
In Fortran, sigils are not used, but all variables starting with the letters I, J, K, L, M and N
are integers by default. Fortran documentation refers to this as "implicit typing", though
explicit typing is always available to allow any variable to be declared with any type. (The
range I-N was chosen to be mnemonic with the first two characters of "integer").
In CLIPS, scalar variables are prefixed with a ? sigil while multifield (i.e. a 1-level list)
variables are prefixed with $?.
In C#, any variable names may be prefixed with @. This is mainly used to allow the use
of variable names that would otherwise conflict with keywords. The @ sigil can also be
applied to string literals, which changes the way they are interpreted (character escapes
are not used and strings can extend over multiple lines). The same is achieved in VB.Net
by enclosing the name in square brackets, as in [end].

14

1. mparte codul surs n atomi lexicali (tokeni).


2. Construiete tabela de simboli.
Un atom lexical (token) este o component singular indivizibil
a unui limbaj unitate lexical.
Ex:
cuvinte cheie n C: while, for, if, else
identificatori - nume de variabile, nume de funcii, nume de constante
nume simbolice - #define PI 3.14

Sintaxa atomilor lexicali este definit, de obicei, de ctre o


gramatic regulat; de aceea pentru recunoaterea lor se poate
utiliza un automat finit determinist construit pe baza unei
expresii regulate.
Etapa se mai numete i lexing sau scanning, iar programul
desemnat s o realizeze poart numele de analizor lexical sau
scanner.

15

16

n tabela de simboli fiecare atom lexical este reprezentat printr-un cod


numeric care specific clasa acestuia i o serie de informaii specifice clasei
din care face parte.
Ex:

Studiind tabela de simboli se poate observa c nu exist o coresponden


biunivoc ntre irurile de intrare (lexeme) i atomii lexicali.
Ex:

Pentru un atom lexical de tip numr trebuie s se memoreze att tipul numrului, ct i valoarea
acestuia.
Pentru un atom lexical de tip nume de variabil trebuie s se memoreze tipul, domeniul de
valabilitate (scope) i valoarea.
Pentru un atom lexical de tip nume de funcie trebuie s se memoreze numrul de parametrii, tipul
fiecrui parametru i modul de transfer al acestora.

Pentru atomul lexical corespunztor unei constante exist mai multe iruri de intrare (n exemplul
anterior 0 i 25)

Analizorul lexical este de obicei implementat printr-o funcie care, ori de


cte ori este apelat (de ctre analizorul sintactic), ntoarce atomul lexical
urmtor.

17

Este necesar n cazul limbajelor care


utilizeaz macrourile (pentru nlocuirea
acestora) sau care permit compilarea
condiional
i
pentru
eliminarea
comentariilor.
Este realizat prin manipularea simbolilor
lexicali.
Ex: macrourile din limbajul C
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
x = min(a, b); ==> x = ((a) < (b) ? (a) : (b));
y = min(1, 2); ==> y = ((1) < (2) ? (1) : (2));
z = min(a + 28, *p); ==> z = ((a + 28) < (*p) ? (a + 28) : (*p));

18

Ex: compilarea condiionat din C: permite ca


o anumit parte din codul surs s fie
ignorat n timpul compilrii, n funcie de
anumite
condiii.
Se
realizeaz
prin
intermediul directivelor condiionale: #if,
#ifdef, #ifndef.
#if expression

controlled text
#endif /* expression */
19

20

Verific dac codul surs este scris potrivit regulilor


gramaticii care definete limbajul surs.
Implic analiza gramatical a secvenei de atomi lexicali
pentru a identifica structura sintactic a programului.
n aceast faz se construiete arborele de derivare:
secvena liniar a atomilor lexicali este nlocuit cu o
structur arborescent, pe baza regulilor gramaticii
formale care definete sintaxa limbajului.
Avnd n vedere cele dou modaliti de construire a unui
arbore de derivare, analiza sintactic poate fi abordat n
dou feluri:
1. ascendent (bottom-up) - shift reduce: deplasare
reducere
2. descendent (top-down) -

21

22

23

Domenii de cercetare ale semanticii sensurile


cuvntului semantic
1. Semantica studiul semnificaiei termenilor n
afara oricrui context (lexicografia)
2. Semantica studiul sistemelor coninutului,
semantica structural
3. Semantica studiul raporturilor dintre termen
(enun) i referent studiul referinei
4. Semantica studiu al condiiilor de adevr ale
enunurilor
5. Semantica studiul sensului particular pe care
termenii sau enunurile le capt n context, n
ansamblul textual
24

Compilatorul adaug informaii semantice arborelui


de derivare i completeaz n mod corespunztor
tabela de simboli.
Poate s fie incorporat n etapa de analiz sintactic.
1. Fiecare definiie a unui identificator este nlocuit
printr-un nume unic (atom lexical unic), iar
informaiile despre fiecare atom lexical unic sunt
adugate n tabela de simboli.
2. Fiecare apariie a unui identificator este nlocuit
cu numele (atomul lexical) unic care i corespunde.
Se fac apoi o serie de verificri semantice (verificri
privind nelesul) se verific dac numele
(identificatorii) nu sunt utilizate ntr-un mod
impropriu.

25

Verificarea tipului (type checking) se verific dac


exist erori privind tipurile folosite
Ex:

Pentru operatorul modulo ambii operanzi trebuie s fie de


tip ntreg: a % b
Pentru operatorii logici (I, SAU, NOT) operanzii trebuie s
fie de tip boolean: !a
Pentru accesarea valorii unui element dintr-un vector
primul identificator trebuie s reprezinte un vector, iar al
doilea trebuie s fie un ntreg: a[b]

Object binding asocierea dintre definiiile funciilor


i claselor i declararea acestora.
Definite assigment verificarea faptului c toate
variabilele locale au fost iniializate nainte de a fi
utilizate.

26

Pentru scrierea codului intermediar pentru program pot fi


folosite mai multe variante:
Chiar arborele de derivare construit anterior;
forma postfix (reverse Polish);
Three address code.
Codul cu trei adrese poate fi scris n dou forme:
A := B op C
op A,B,C
Ex: Translatarea expresiei A/B*C+D n cod cu trei adrese (prin
introducerea i utilizarea a trei variabile temporare) este:

n forma postfix (forma Polonez invers) fiecare operator


urmeaz dup toi operanzii si.
Ex: 3+4 se scrie 3 4 +

27

Importana unei soluii de back-up

28

Componenta back-end a compilatorului este


responsabil de realizarea urmtoarelor
etape:
1. Analiza
2. Optimizarea
3. Generarea codului

29

Etapa const n adunarea de informaii despre


program, pornind de la codul intermediar
construit pe baza codului surs.
Au loc:
Analiza fluxului de date cu scopul de a construi usedefine chaines
Analiza dependenelor
Analiza alias-urilor
Analiza pointerilor
Analiza escape
Construirea grafului de apeluri
Construirea grafului fluxului de control

Toate informaiile obinute n aceast etap vor


sta la baza optimizrii ulterioare.

30

Codul intermediar este transpus ntr-o form echivalent


care este mai rapid sau de dimensiuni mai mici.
Cuprinde:

Inline expansion
Dead code elimination
Constant propagation
Loop transformation
Register allocation
Automatic parallelization

Optimizarea se poate face i direct asupra codului surs


nainte de compilare, sau asupra codului generat (n limbaj
de asamblare sau n limbaj main).
Efectuarea optimizrii duce la ncetinirea procesului de
compilare, dar codul rezultat va rula mai rapid i/sau va
necesita mai puin memorie.

31

Ex:

Optimizarea buclelor: optimizare global, care necesit


analiza i modificarea unor pri mari de cod. Pentru
codul surs:
for(int r = 0; r < 100; r++ )

// alte calcule
float pi = 4 * arctan(1);
aria = pi * r * r;

mai eficient dac instruciunea float


pi=4*arctan(1); este mutat n afara buclei for. Mutarea ei se
poate face mult n faa instruciunii for, de unde i clasificarea
ca optimizare global.
Execuia

este

32

Optimizarea peephole (limbaj de asamblare sau limbaj


main): optimizare local, n care instruciunile sunt
analizate n grupuri de cteva (de exemplu cte dou),
iar modificrile se fac numai n interiorul unui grup.
Ex: Pentru un procesor cu un singur registru, codul
intermediar n trei adrese:

va fi translatat n codul obiect:

33

Codul intermediar transformat este translatat


n limbajul de ieire, i anume limbajul
main a sistemului.
Ex:
Pentru un procesor care are un singur registru, din
codul intermediar A:=B+C (scris ADD A,B,C n
formatul codului cu trei adrese) se genereaz:
LOAD B
ADD C
STORE A

34

n fiecare etap a compilrii pot fi identificate erori specifice.


Ex:
n analiza lexical: un ir de caractere din codul surs nu
corespunde niciunui atom lexical.
n analiza sintactic: irul de atomi lexicali identificai nu
formeaz o propoziie corect din punct de vedere sintactic.
n analiza semantic: se gsesc erori la verificarea tipurilor.
Problem: Cum se face tratarea erorilor: Dup identificarea unei
erori analiza continu sau se oprete?
Raportrile unei erori trebuie sortate n ordinea de apariie n
cadrul codului surs i afiate n mod corespunztor
utilizatorului.
Erorile depistate n urma verificrilor efectuate pot duce la
rejectarea programului (nu se poate genera cod obiect) sau la
afiarea de mesaje de atenionare (warnings), cu generarea de
cod obiect.

35

These are some of the error messages produced by Apple's MPW


C compiler. They are all real. (If you must know I was bored one
afternoon and decompiled the String resources for the compiler.)

"String literal too long (I let you have 512 characters; that's 3
more than ANSI said I should)
"...And the lord said, 'lo, there shall only be case or default
labels inside a switch statement'
"A typedef name was a complete surprise to me at this point in
your program
"You can't modify a constant, float upstream, win an argument
with the IRS, or satisfy this compiler
"This struct already has a perfectly good definition
"type in (cast) must be scalar; ANSI 3.3.4; page 39, lines 10-11 (I
know you don't care, I'm just trying to annoy you)"

36

"Can't cast a void type to type void (because the ANSI spec. says
so, that's why)
"Huh?
"Can't go mucking with a 'void *'
"We already did this function
"This label is the target of a goto from outside of the block
containing this label AND this block has an automatic variable
with an initializer AND your window wasn't wide enough to read
this
whole
error message
"Call me paranoid but finding '/*' inside this comment makes me
suspicious
"Too many errors on one line (make fewer)
"Symbol table full - fatal heap error; please go buy a RAM
upgrade from your local Apple dealer

37

http://academic.udayton.edu/saverioperugini/co
urses/cps343/lecture_notes/grammars.html
http://homedir.jct.ac.il/~rafi/formcomp.pdf
Umberto Eco, Cinci sensuri ale cuvntului semantic, De la
arbore la labirint, edit. POLIROM, 2009.

Pentru prile care intenionam s fie amuzante:


http://lifegeeked.wordpress.com/
http://flyingtraincircus.com/category/computer-related/
http://blagbert.blogspot.com/
http://www.georgehernandez.com/h/aablog/2005/04.asp

38

S-ar putea să vă placă și