Sunteți pe pagina 1din 33

Capitolul 1.

Introducere n limbaje de programare


Acest capitol introduce problematica limbajelor de programare. Pentru nceput
vom evidenia necesitatea studierii limbajelor pentru a putea realiza
comunicarea om-calculator. Pornind de la comunicarea interuman prin
intermediul limbilor (vorbite, scrise, vizuale), vom defini conceptul de limbaj de
programare. Apoi vom insista asupra unor noiuni introductive de limbaje de
programare. Astfel, vom realiza o clasificare a limbajelor de programare,
insistnd asupra tipurilor de limbaje, asupra gradului lor de abstractizare
respectiv de apropiere de descrierea i rezolvarea anumitor tipuri de probleme.
Vom continua prin a realiza o scurt incursiune n istoria limbajelor de
programare, evideniind evoluia lor n timp, concomitent cu evoluia
paradigmelor de gndire n informatic. Partea final a capitolului puncteaz
cteva aspecte caracteristice care trebuie studiate i menionate la referirea
unui limbaj de programare.

1.1. Definirea limbajelor de programare


Comunicarea interuman este indispensabil n viaa de zi cu zi. Pentru
realizarea acesteia, oamenii folosesc diverse modaliti, limbajele reprezentnd
poate cea mai important facilitate de comunicare. Una din primele aptitudini
importante pe care un copil o dobndete este s vorbeasc. El nva limba
matern. De obicei, aceasta i este suficient pentru comunicarea de zi cu zi cu
ali indivizi din propria societate. Dac ns, un individ cltorete, el are nevoie
s cunoasc i alte limbi pentru a se putea descurca, pentru a putea comunica
cu ali oameni din alte societi ale lumii. Cu toate c, n principiu, oamenii
atribuie nelesuri similare pentru lucruri similare, ei vorbesc (exprim) aceste
nelesuri n limbi diferite. Diferena se manifest att la nivelul sunetelor i
nlnuirii acestora pentru a forma cuvintele ct i la nivelul simbolurilor grafice
folosite. A nva s vorbim ntr-o alt limb presupune a nva s rostim
cuvintele din limba respectiv, s le nlnuim de o manier potrivit conform
regulilor gramaticale a limbii nvate i s folosim simbolurile specifice acestei
limbi pentru a descrie vizual sintagmele de comunicare. Dac nu mnuim
corespunztor aceste elemente, atunci cnd vom fi pui n situaia de a
comunica cu cineva care nelege doar limba respectiv, vom eua n
ncercarea noastr.

10

Capitolul 1. Introducere n limbaje de programare

Am realizat aceast scurt introducere pentru a putea realiza o comparaie


ntre actele de comunicare inter-uman i comunicarea dintre om i calculator.
n aceast comunicare, putem vedea calculatorul ca pe un partener care e
dispus s ne rezolve problemele. Pentru aceasta, trebuie s-i specificm modul
n care s rezolve aceste probleme. Putem s realizm acest lucru utiliznd
algoritmii. Dar algoritmii trebuie descrii ntr-un limbaj inteligibil pentru
calculator. Putem vedea aceast comunicare ca un caz special al unei
solicitri. Dac cerem ceva cuiva, atunci va trebui s folosim cuvinte, expresii
pe care acesta s le neleag.
Conform Dicionarului Explicativ al Limbii Romne, prin limb se nelege un
sistem de comunicare alctuit din sunete articulate, specifice omului, prin care
acesta i exprim gndurile sau dorinele. Astfel, un limbaj este un mijloc de
comunicare a ideilor prin sunete i culoare, reprezentnd un mijloc de
transmitere a informaiei ntre indivizii unei categorii [Nichi 2005].
Orice limbaj are la baz simboluri care formeaz limbajul respectiv. Astfel,
limba vorbit are la baz sunete, limbajele scrise au la baz literele, limbajele
vizuale au la baz simbolurile grafice. Semiotica este ramura tiinei care se
ocup cu studiul simbolurilor.
Revenind la comunicarea dintre om i calculator, trebuie s definim noiunea de
limbaj de programare. Astfel, prin limbaj de programare nelegem o notaie
sistematic prin care este descris un proces de calcul [Prv 1996]. Un proces
de calcul este constituit dintr-o mulime de pai pe care o main i poate
executa pentru a rezolva o anumit problem.
Astfel, un limbaj de programare este un intermediar ntre realitatea
reprezentrilor utilizatorului asupra problemei de rezolvat i realitatea
calculatorului cu care lucreaz [erbnai 1987]. La rezolvarea unei probleme
cu calculatorul, un programator trebuie s priveasc fiecare element al
limbajului din 2 puncte de vedere:
unul logic, al problemei; astfel programatorul trebuie s tie ce nelege s
reprezinte din problem cu ajutorul elementului de limbaj
unul fizic, al implementrii, care se refer la ceea ce realizeaz calculatorul
la execuia elementului de limbaj considerat.
Programul este un compromis ntre cele 2 puncte de vedre. Astfel,
programatorul trebuie s-i reprezinte i s neleag urmtoarele universuri:
universul problemei
universul limbajului de programare
universul calculatorului
Aceste trei universuri sunt n general diferite. Pentru a realiza corespondena
ntre acestea, exist definite diverse activiti ale informaticii. Figura 1 surprinde
corespondena ntre universurile limbajelor de programare.

1.1. Definirea limbajelor de programare

11
Universul
calculatorului

Universul
problemei
Simulare

Elaborare
program

Compilare

Universul limbajului
de programare

Figura 1.

Universurile unui limbaj de programare [erbnai


1987].

Orice limbaj are 3 aspecte caracteristice:


aspectul sintactic
aspectul semantic
aspectul pragmatic
Sintaxa unui limbaj conine ansamblul regulilor prin care pornind de la
simbolurile de baz care alctuiesc alfabetul limbajului, se construiesc structuri
compuse [Nichi 2005].
Mulimea regulilor sintactice care descriu ansamblul propoziiilor sau a
formulelor corecte din cadrul limbajului formeaz gramatica.
Deci, sintaxa i gramatica ne ajut s identificm modul n care putem combina
simbolurile de baz ale limbajului pentru a produce elemente acceptate de
limbaj. Ele reprezint imperative riguroase, care pot fi formalizate matematic.
Sintaxa se descrie teoretic cu ajutorul sistemelor formale. Urmtoarele
elemente se utilizeaz pentru descrierea sintaxei unui limbaj:
diagramele sintactice
arbori de analiz
metalimbaje (BNF Backus Naur Form, EBNF Extended Backus Naur
Form, Asn.1)
Prin semantic se nelege sensul construciilor sintactice. Ea reprezint un set
de reguli ce determin semnificaia propoziiilor dintr-un limbaj. Este vorba de
reguli de evaluare a acestor propoziii n termenii unor mulimi de valori
cunoscute de limbajul respectiv. Astfel, semantica reprezint nelesul fiecrei
formule corecte admise de gramatic.
Pragmatica se refer la capacitatea de a utiliza construciile sintactice i
semantice. Referitor la nelegerea aspectului pragmatic al limbajelor, putem s

12

Capitolul 1. Introducere n limbaje de programare

se nchipuim urmtorul exemplu: o persoan poate cunoate foarte bine


aspectele sintactice i semantice ale unui limbaj, dar nu are capacitatea de a
utiliza corect aceste reguli. De asemenea, exist persoane care vorbesc
(folosesc) o limb fr a cunoate aspectele sintactice i semantice ale
acesteia. Pragmatica nu se poate formaliza.
n capitolul 2 vom trece la prezentarea succint a formalizrii elementelor de
limbaje de programare.

1.2. Clasificarea limbajelor


Referitor la limbaje, putem s vorbim de o clasificare general a acestora.
Astfel, limbajele pot fi naturale sau artificiale. Referindu-ne strict la limbajele de
programare, acestea pot fi clasificate din perspectiva paradigmelor de
programare sau a nivelului de abstractizare a limbajului. n aceast seciune
vom descrie succint clasificarea general a limbajelor i vom insista asupra
clasificrii limbajelor de programare.

1.2.1. Clasificarea general a limbajelor


Pe plan general, exist 2 tipuri de limbaje: naturale i artificiale.
Limbajele naturale sunt cele istorice, precum limba romn, englez etc.
Limbajele artificiale au fost create de oameni n diverse scopuri. Astfel exist:
jargoane profesionale, folosite la comunicarea n cadrul diverselor grupuri
profesionale. Exist astfel un limbaj matematic, medical, economic, bursier
etc.
limbaje pentru comunicare ntre dispozitive. Aceste limbaje se mai numesc
i protocoale. Ele ajut la stocarea i transmiterea informaiei ntre diverse
componente ale unor medii (de obicei artificiale). De exemplu, pentru
comunicarea n reelele de calculatoare se folosete protocolul TCP/IP sau
alte protocoale de reea (de nivel mai mult sau mai puin abstract). Pentru
comunicarea la nivel software se pot folosi limbaje bazate pe descrieri
specifice de domeniu, descrise n XML.
limbaje de pentru comunicarea dintre om i dispozitive. Din aceast
categorie fac parte limbajele de programare.

1.2.2. Clasificarea limbajelor de programare din perspectiva


nivelului de abstractizare
Din punct de vedere al nivelului, limbajele se nscriu n 2 mari categorii:
limbaje de nivel inferior
limbaje de nivel superior

1.2. Clasificarea limbajelor

13

Cu ct un limbaj este mai apropiat de simbolurile efective, binare, cu care


lucreaz calculatorul, limbajul este de nivel mai sczut. Figura 2 descrie
ierarhizarea limbajelor de programare n funcie de nivel.
Limbaj de nivel
superior
Limbaj de
asamblare

Compilator
Interpretor

asamblor

Microprocesor
Cod masina

Figura 2.

Ierarhizarea limbajelor de programare n funcie de


nivel.

Limbajul sau codul main reprezint un limbaj binar cu care lucreaz efectiv
procesorul. De obicei, fiecare procesor are propriul su cod main, definit fizic
de constructorul procesorului. Codul main aparine primei generaii de
limbaje de programare.
Limbajele de asamblare sau macroasamblare se situeaz deasupra codului
main i sunt formate prin coresponden direct ntre succesiuni binare i
termeni (eventual prescurtai) din vorbire. Limbajele de asamblare fac parte din
generaia 2-a de limbaje de programare.
Programele scrise n cod main sau limbaje de asamblare pot fi considerate
optimale pentru calculator, deoarece acesta poate s execute n mod direct,
fr o alt conversie un asemenea cod. Dezavantajele principale ale acestora
rezid n dificultatea acestor limbaje. Productivitatea activitii de programare
este foarte sczut. Limbajele din primele dou generaii sunt specifice pe
procesor, adic gradul lor de portabilitate este foarte sczut. Prin portabilitate
se nelege caracteristica unui program de a putea fi rulat pe diverse
calculatoare (sau tipuri de calculatoare) fr modificri, sau cu modificri
minimale.
Limbajele de nivel superior aparin generaiilor 3-a, 4-a i 5-a de limbaje de
programare. Aceste limbaje se apropie tot mai mult de nelegerea uman, de
reprezentri specifice n termenii problemei de rezolvat.
Limbajele de generaia 3 conin limbaje pentru prelucrarea datelor neorganizate
n baze de date. Ele sunt limbaje de uz general, respectiv de programare
automat. Aceste limbaje permit programatorului s exprime rezolvarea
problemei ntr-un limbaj mai apropiat de limbajul natural. Includem n aceast
categorie limbaje precum Fortran, C/C++, Pascal etc.

14

Capitolul 1. Introducere n limbaje de programare

Limbajele de generaia 4 sunt destinate n special prelucrrii datelor organizate


n baze de date. Ele sunt utilizate pentru realizarea de programe comerciale, a
cror obiectiv principal este manipularea unor cantiti mari de date. Limbajele
din generaia 4-a sunt de obicei uor de nvat i aplicat, i sunt destinate unor
categorii mai mari de utilizatori. Aceste limbaje pun accentul mai mult pe
funcionalitatea oferit dect pe tehnicile de programare.
Limbajele din generaia 5-a sunt limbajele inteligenei artificiale. n aceast
categorie putem include limbajele logice pentru manipulare de simboluri i
limbajele de gestiune a bazelor de cunotine.
Limbajele de nivel superior prin caracteristicile lor, asigur o productivitate
corespunztoare a muncii de programare. Astfel, ele se caracterizeaz prin:
faciliti legate de elaborarea programelor. Limbajul se apropie de multe ori
de limbajul natural sau de dialecte ale acestuia
sunt standardizate: se asigur astfel independena de main i deci
portabilitatea
exist o productivitate bun a elaborrii programelor. Pentru multe limbaje
s-au dezvoltat metodologii de lucru n activitatea de dezvoltare a
programelor pentru a se asigura posibilitatea de lucru n echip respectiv a
se asigura extensibilitatea programelor. Ingineria programrii este ramura
tiinei calculatoarelor care se ocup cu studiul metodelor de dezvoltare
organizat a programelor informatice.
Pentru execuia programelor scrise ntr-un limbaj de nivel superior, acestea
trebuie convertite n cod de nivel inferior specific mainii pe care se dorete
rularea programului. Programele care asigur aceste conversii se numesc
programe de traducere. Programele de traducere sunt de 3 tipuri:
compilatoare
interpretoare
traducere n dou faze.
Compilatoarele traduc programul dintr-un limbaj surs (de ex. C) ntr-un limbaj
obiect (de ex. cod main). Compilatoarele nu execut programul compilat.
Limbajul obiect nu trebuie s fie n mod obligatoriul limbajul main. Un tip
special de compilatoare sunt precompilatoarele care traduc o extensie a unui
limbaj ntr-un limbaj de baz. De multe ori activitatea de compilare este
realizat n mai multe faze. Vom insista asupra fazelor traducerii unui program
surs n program obiect executabil n capitolul 2.
Interpretoarele traduc instruciune cu instruciune un cod surs, i pe msur
ce realizeaz traducerea unei instruciuni o i execut. Basic este un exemplu
de limbaj interpretat. Avantajul interpretoarelor fa de compilatoare este c
dac apare o eroare ntr-o instruciune ea se poate corecta pe loc. Limbajele
interpretate sunt ns, de obicei, limbaje simple, i nu permit astfel realizarea
unor programe foarte complexe.

1.2. Clasificarea limbajelor

15

Traducerea n dou faze presupune traducerea codului din cod surs ntr-un
cod intermediar care apoi este rulat pe o main virtual. Limbajele care
funcioneaz pe acest principiu se numesc limbaje pseudo-compilative.
Exemple de limbaje pseudo-compilative sunt Java i limbajele din familia .NET.

1.2.3. Paradigmele limbajelor de programare


Prin paradigm se nelege n general modelul sau arhetipul unui proces sau
sistem. Paradigmele de programare sunt colecii individualizate de caracteristici
de evaluare i criterii de abstractizare care determin i difereniaz clasele de
limbaje de programare [Prv 1996]. Exemple de astfel de criterii sunt structura
programului, starea execuiei, metodologia programrii etc.
Clasificrile limbajelor de programare dup paradigme difer de la autor la
autor. Vom prezenta n cele ce urmeaz cteva paradigme de programare
considerate mai importante n istoria limbajelor de programare [Nichi 2005].
Trebuie s menionm c ideile cuprinse n limbajele de programare sunt n
continu schimbare, datorit faptului c, permanent, apar limbaje noi, care de
multe ori nu pot fi clasificate conform criteriilor existente.

1.2.3.1. Paradigma programrii procedurale


Clasificnd limbajele dup aceast paradigm, ele se mpart n limbaje
procedurale i limbaje neprocedurale.
Limbajele procedurale se caracterizeaz prin faptul c utilizatorul descrie pas
cu pas algoritmul de rezolvare a problemei, printr-un ir de instruciuni care
formeaz o procedur, rutin, subrutin sau funcie. Din acest punct de vedere,
programul este o mulime ierarhic de blocuri i proceduri. Exponentul clasic al
acestei paradigme este ALGOL60. Din aceast categorie amintim limbajele
Pascal, C, PL/I, Ada etc.
n limbajele neprocedurale, utilizatorul nu mai descrie algoritmul de rezolvare,
el doar indic sistemului ce anume dorete. n acest caz, sistemul este
responsabil s gseasc calea de rezolvare a problemei.

1.2.3.2. Paradigma programrii structurate


Programarea structurat este n strns legtur cu programarea procedural.
Muli autori consider aceste dou paradigme ca fiind de fapt una singur.
Fundamentul programrii structurate este urmtorul enun: orice procedur
care are o singur intrare i o singur ieire poate fi reprezentat prin cele trei
structuri fundamentale din algoritmic: structura liniar, structura ramificat i
structura repetitiv. Astfel, s-a demonstrat c instruciunile de salt necondiionat
din programe nu mai sunt necesare, i astfel se poate ordona activitatea de
scriere de cod. Alternativa la programarea structurat este programarea stil

16

Capitolul 1. Introducere n limbaje de programare

spagetti, care reprezint un stil confuz de programare cu multe salturi


necondiionate.
Recomandm la nivel microscopic de programare utilizarea programrii
structurate, adic folosirea n program doar a structurilor algoritmice
fundamentale. Un program structurat este totdeauna mult mai lizibil i mai
flexibil dect unul nestructurat.
Exponentul principal al programrii structurate este Pascal.

1.2.3.3. Paradigma programrii modulare


Programarea modular const n descompunerea programului n module
independente, atomice. Principala idee este ncapsularea. Astfel, datele interne
modulului sunt ascunse utilizatorului. Accesul la date se poate realiza doar prin
interfa. n acest context, un modul are dou componente: interfaa i
implementarea.
Paradigma programrii modulare extinde programarea procedural i
structurat prin introducerea unui nivel superior de abstractizare: modulul. Se
face astfel un pas important ctre programarea obiectual.
Cele mai cunoscute limbaje modulare sunt Modula i Ada.

1.2.3.4. Paradigma programrii obiectuale


n aceast seciune vom descrie doar succint caracteristicile paradigmei
obiectuale. Partea a doua a prezentei lucrri conine o dezvoltare i o
prezentare mai larg a conceptelor i metodelor de programare obiectual.
Un obiect definete o entitate care conine informaie i are un comportament.
Alte obiecte pot face uz de comportamentul obiectului pentru a obine
informaia ataat obiectului. n programarea obiectual, orice entitate din
lumea real poate fi considerat un obiect. Programul este considerat ca un
ansamblu de obiecte care interacioneaz ntre ele.
n cadrul paradigmei obiectuale, obiectele reprezint ncapsularea datelor cu
codul. Deci obiectele au o structur i o stare. Fiecare obiect definete
operaiile care pot accesa i manipula aceast stare. Obiectele sunt uniti
atomice n programe. Datele interne ale obiectelor se mai numesc proprieti,
iar partea de cod formeaz metodele. Comunicarea ntre obiecte se face prin
mesaje. Astfel, un apel de metoda a unui obiect poate fi considerat ca o
transmitere de mesaj ctre obiectul apelat.
Obiectele de acelai tip pot fi grupate n clase. Din acest punct de vedere,
putem considera obiectele ca i instanieri ale claselor. Clasele pot fi relaionate
unele cu altele, prin diverse tipuri de relaii. Astfel, avem relaiile de agregare
prin care o clas se compune din alte clase, sau de generalizare/specializare,

1.2. Clasificarea limbajelor

17

prin care o clas este caz particular (specializat) al unei superclase. Astfel, prin
compoziie i motenire se asigur reutilizarea codului.
Principalul avantaj al programrii obiectuale fa de paradigmele anterioare
este realizarea polimorfismului. Prin polimorfism se nelege proprietatea unui
nume de a fi utilizat cu nelesuri diferite. Cea mai important form de
polimorfism este polimorfismul de tip, prin care tipul referinei se adapteaz la
tipul obiectului.
Smalltalk este limbajul care a introdus paradigma obiectual. Acest limbaj a
fost dezvoltat n limbajele Smalltalk80 i Smalltalk86. C++ reprezint extensia
obiectual a limbajului structurat C. De asemenea Java implementeaz
caracteristicile paradigmei obiectuale.

1.2.3.5. Paradigma programrii funcionale


n cadrul acestei paradigme programul este descris ca un ansamblu de funcii
apelate, n general, recursiv. Ele pot interveni n structurile de date ale
limbajului dar i n cadrul codului, fiind permise funcii de funcii (se accept
operaia de compunere de funcii).
Printre caracteristicile acestor limbaje amintim faptul c ele nu au instruciuni de
atribuire i nu genereaz efecte secundare la apelul unei funcii. Prin efect
secundar la apelul unei funcii nelegem existena unui efect al rulrii funciei
asupra apelantului ei.
Fundamentul matematic al limbajelor funcionale l constituie scrierea funciilor
ca i expresii lambda.
Exemplul tipic de limbaj funcional este LISP. El se bazeaz pe gestiunea
listelor. Un alt limbaj din aceast familie este ML, limbaj generic utilizat la
studiul teoretic al programrii funcionale.

1.2.3.6. Paradigma programrii logice


n programarea logic un program este alctuit din fapte i reguli pe baza
crora programul urmeaz s genereze concluzii. Limbajele din aceast
paradigm se mai numesc limbaje declarative deoarece specificarea unui
program nseamn specificarea unor declaraii. Programul nu instruiete
calculatorul cum s rezolve problema, ci spune calculatorului cum dorim s
arate soluia problemei. n sensul programrii logice, programul indic
procesorului metodele i informaiile necesare pentru extragerea unei soluii de
forma dorit.
Baza matematic a acestor limbaje o constituie sistemele logice formale. De
obicei, acestea se bazeaz pe logica predicatelor de ordinul I, care poate fi
extins sau mbogit cu alte axiome. Astfel, se pot obine logici modale,

18

Capitolul 1. Introducere n limbaje de programare

temporale sau monotonice care pot s furnizeze mecanisme de deducie


folosite n limbajele logice.
Prolog reprezint exemplul clasic de limbaj din aceast categorie. El reprezint
transcrierea ntr-un limbaj de programare a logicii predicatelor de ordinul I.
Limbajele logice stau la baza motoarelor de inferen din sistemele expert.

1.2.3.7. Paradigma programrii concurente i distribuite


Aceast paradigm se bazeaz pe faptul c dou sau mai multe programe,
respectiv pri ale aceluiai program se execut n paralel pe acelai procesor
sau pe procesoare diferite. Astfel, aceast paradigm nu mai respect
principiul linearitii n execuia instruciunilor componente ale unui program.
Execuia aciunilor unui program poate fi independent sau pot depinde de
execuia instruciunilor altui program care se execut n paralel. Astfel, pentru
sincronizarea execuiei programelor se folosesc tehnici de sincronizare i
serializare, semafoare respectiv semnturi de timp. Astfel, se asigur
comunicarea ntre procese, accesul concurent la resurse, partajarea resurselor.
Aspectul de distribuire se refer la utilizarea concomitent resurselor din mai
multe locaii, respectiv la mprirea sarcinilor de executat i realizarea acestora
de mai multe entiti de procesare.
Limbajele concurente sunt de obicei extensii ale limbajelor din alte paradigme.
Astfel, exist extensii concurente pentru C, Pascal, Fortran, Prolog. Exemple
de limbaje concurente sunt CSP, Linda, Occam, Parlog.

1.2.3.8. Alte paradigme de programare


Muli autori consider i alte paradigme de programare.
Astfel, pentru programarea la nivelul bazelor de date avem limbaje de
programare precum SQL sau dBase. Acestea sunt destinate asigurrii unei
gestiuni corecte i consistente a bazelor de date.
Unii autori consider programarea vizual ca o paradigm de programare. n
cadrul acestei paradigme ei ncadreaz mediile de dezvoltare rapid a
1
programelor . De obicei, ns aceste medii sunt destinate realizrii activitii de
programare pentru un anume limbaj, i astfel, considerm c ele nu reprezint
o nou paradigm de limbaje de programare.
2
Limbajele bazate pe marcatori sunt folosite de obicei pentru structurarea i
reprezentarea informaiei i mai puin pentru realizarea activitii de
programare. Ele se bazeaz pe SGML, un limbaj standardizat, independent de
platform, utilizat la realizarea help-urilor i a componentelor sale. n cadrul

Rapid Application Development (RAD) environments, n lb. Englez

Markup Languages, n lb. Englez

1.2. Clasificarea limbajelor

19

acestei categorii putem aminti XML, limbaj specializat pentru structurarea


informaiei i HTML limbajul World Wide Web-ului.
Programarea bazat pe ageni reprezint o nou paradigm de programare.
Agenii reprezint un nivel de abstracie superior obiectelor, n sensul c agenii
sunt entiti software autonome capabile de comportament pro-activ. Aceasta
nseamn, pe de-o parte, faptul c agenii au o stare i un comportament
propriu iar, pe de alt parte, faptul c acest comportament se poate executa din
dorina agentului, fr s fie nevoie invocarea comportamentului de o alt
entitate de program. Comportamentul agentului este ghidat mai mult de
obiectivele, credinele i inteniile agentului dect de cereri explicite ale altor
ageni. Teoria agenilor reprezint o nou idee de realizare a programelor
software mai mult dect o baz care s conduc la realizarea de limbaje de
programare specifice. Totui, exist limbaje specifice precum Telescript,
Agents, AgentTcl etc. De multe ori pentru realizarea de sisteme cu ageni sau
care respect principiile programrii cu ageni se utilizeaz limbaje de
programare obiectuale generale (precum Java) care sunt extinse cu faciliti
destinate agenilor. Se creeaz aa-numitele platforme multi-agent n care se
pot crea (programa) ageni care s rezolve anumite sarcini. Amintim n cadrul
platformelor multi-agent tool-urile FIPA-OS, JADE, IBM Aglets, etc. n cadrul
paradigmei programrii cu ageni se utilizeaz i limbaje de reprezentare a
cunotinelor agenilor i de facilitare a comunicrii inter-agent. n aceast
categorie putem nscrie KQML, KIF i ACL.

1.3. Istoricul i evoluia limbajelor de programare


n aceast seciune vom descrie principalele borne care au marcat istoria
limbajelor de programare, mpreun cu elementele de noutate aduse de fiecare
limbaj important din punct de vedere a evoluiei istoriei informaticii. Tabelul 1
prezint o legarea principalelor limbaje de programare de momentul apariiei.
Figura 3 conine arborele limbajelor de programare, reflectnd influenele i
genealogia limbajelor de programare. Acestea sunt preluate dup [Prv 1996].
Dezvoltarea limbajelor de programare este strns legat de evoluia tiinei
calculatoarelor. Astfel, pe msur ce mainile de calcul devin tot mai sofisticate
i performante, evolueaz i limbajele i paradigmele de programare, oferind
noi faciliti utilizatorilor de maini de calcul.
Limbaj
Fortran

An
1957-si

Autori

Predecesor

J. Backus
(IBM)

Algol60

1960-s

Comitet

Cobol

1960-s

DOD

Scop
Calcule numerice

Fortran

Calcule numerice
Prelucrri de date
economice

20

Capitolul 1. Introducere n limbaje de programare

APL

1960-si

K. Iverson
(Harvard)

Prelucrri de tablouri

Lisp

1962

J. McCarthy
(MIT)

Prelucrri de liste

Snobol

1966-si

R. Griswold
(Bell)

Prelucrri de iruri de
caractere

PL/1

1964-s

IBM

Fortran,
Algol60, Cobol

Uz general

Simula67

1967

O.J. Dahl

Algol60

Simulare

Algol68

1968-s

Comitet

Algol60

Uz general

Pascal

1971

N. Wirth (ETH
Zurich)

Algol60

Uz general, scop
educaional

Prolog

1972

Univ. Marsilia

1974

D. Ritchie
(Bell)

Algol60, BCPL

Programare de sistem

Concurrent
Pascal

1975

P.B. Hansen
(CalTech)

Pascal

Programare concurent

Euclid

1977

Comitet

Pascal

Programare de sistem
verificabil

Modula

1977

N. Wirth

Pascal

Programare de sistem n
timp real

Ada

1979

J. Ichbiah (CIIBull)

Pascal,
Simula67

Uz general, aplicaii hibride

Smalltalk

1980

Xerox PARC

Simula67

Programare orientat
obiect

C++

1984

B. Stroustrup

Programare orientat
obiect

Oberon

1987

N. Wirth

Pascal,
Modula

Programare orientat
obiect

Modula-3

1988

DEC, Olivetti

Modula

Limbaj puternic modular,


orientat obiect

Java

1995

Sun

Tabelul 1.

Programare logic

Limbaj orientat obiect,


traducere n dou faze
3

Principalele limbaje de programare .

n 1944 maina numit Mark I realizat de IBM a fost primul calculator capabil
s execute o secven lung de operaii aritmetice i logice. n 1946 ENIAC
(Electronic Numerical Integrator And Calculator) devine predecesorul primei
generaii de calculatoare.

si nseamn specificare i implementare, iar s nseamn numai specificare

1.3. Istoricul i evoluia limbajelor de programare

21

n 1959 apare a doua generaie de calculatoare, bazat pe utilizarea


tranzistorilor. Calculatoarele din a 2-a generaie sunt de dimensiuni mai reduse,
mai rapide, mai ieftine i mai fiabile.
Fortran

Algol60

1960

Cobol

Lisp

CPL
PL/1

BCPL
Simula67

Algol68
Pascal

1970

Prolog
C

Modula-2
Ada
C cu clase

1980

Smalltalk

Objective
C

ANSI C

C++
Modula-3
1990

Ada9X

Figura 3.

Arborele genealogic al limbajelor de programare.

n 1965 se introduc circuitele integrate, ceea ce reprezint un semnificativ salt


tehnologic. n acest moment ncepem s vorbim de cea de-a 3-a generaie de
calculatoare. Circuitele integrate au permis pentru prima oar obinerea unei
viteze de calcul de peste un milion de operaii pe secund.
Din 1970 putem vorbi de cea de-a 4-a generaie de calculatoare, prin
dezvoltarea microprocesorului. Acesta era un dispozitiv de calcul independent,
care, integrat n maini de calcul a condus la realizarea unor computere mai
rapide, mai mici i mai ieftine.

22

Capitolul 1. Introducere n limbaje de programare

Din acel moment pn n zilele noastre am asistat la o adevrat explozie


tehnologic din punct de vedere hardware. Calculatoarele de azi sunt capabile
de performane greu de imaginat cu cteva decenii n urm.
Bazele proiectrii calculatoarelor au fost puse n 1940 de matematicianul John
von Neumann, prin descrierea arhitecturii von Neumann pentru maini de
calcul. Aceast arhitectur a influenat puternic modul de dezvoltare a artei
programrii. Figura 4 descrie schematic structura unui calculator von Neumann.
Limbajele de programare care au derivat din aceast arhitectur sunt
cunoscute i sub numele de limbaje imperative, datorit faptului c permit
programatorului s-i specifice cerinele printr-o secven de instruciuni care
s indice exact ceea ce trebuie fcut pentru rezolvarea problemei.
intrari

Unitate aritmetica si logica


Unitate de control

Instructiuni

iesiri

Date

Memorie: programe si date

Figura 4.

Arhitectura von Neumann

Punctele istorice pe care le-am marcat n paragrafele precedente au avut un


impact major asupra dezvoltrii limbajelor de programare. Din momentul anilor
70, dezvoltarea limbajelor de programare a ncercat s in pasul cu
dezvoltrile hardware, dar evoluia limbajelor de programare a luat o cale
distinct. Vom descrie succint principalele limbaje de programare care au
marcat aceast istorie.
La mijlocul anilor 50, n cadrul firmei IBM, s-a studiat posibilitatea realizrii unui
translator algebric. Astfel, echipa condus de John Backus a realizat n 1954
specificaia 0 a limbajului Fortran. Primul compilator de Fortran a fost realizat n
1957 odat cu specificaia 2-a a acestui limbaj. Acest limbaj a devenit foarte
popular datorit faptului c firma IBM l-a oferit gratuit. Fortran reprezint primul
limbaj de programare de nivel nalt. Are o sintax apropiat de scrierea
matematic. In Fortran linia de cod surs are un format fix cu 4 cmpuri, tipul
variabilelor este specificat printr-o convenie standard. Limbajul introduce
instruciunile IF pentru ramificare i DO pentru realizarea de cicluri.
Limbajul Algol cu versiunea de referin Algol60 a avut o contribuie
remarcabil la dezvoltarea limbajelor de programare. Din Algol au derivat o
serie de limbaje de programare. Proprietile principale ale unui limbaj din
familia Algol sunt:
este algoritmic

1.3. Istoricul i evoluia limbajelor de programare

23

este imperativ (algoritmul este considerat o secven de modificri ale


memoriei)
are ca i uniti de baz blocul i procedura
conine conceptele de tip i verificare a tipului
are o specificare prin reguli sintactice
este compilativ
Algol nu a devenit foarte popular datorit faptului c nu a prevzut intrri i
ieiri standard, nu avea un mecanism facil de transmitere a parametrilor prin
nume i nu a fost susinut de IBM (care a promovat puternic limbajul Fortran)
Tot la nceputul anilor 60 a aprut i cel de-al 3-lea limbaj de programare de
4
nivel nalt Cobol . Limbajul se impune repede pe pia datorit sprijinului
puternic al guvernului SUA i devine cel mai utilizat limbaj de programare n
deceniul 7. Cobol introduce descrierea datelor independent de main, punnd
bazele sistemelor de gestiune a bazelor de date. Instruciunea if-then-else
apare pentru prima dat n form complet n Cobol. Pentru creterea lizibilitii
5
programelor Cobol permite folosirea de cuvinte n plus .
Linia Algol este continuat cu limbaje precum Algol-W, Algol68, Euler i mai
apoi Pascal. Tot pe linia Algol-ului apare i limbajul Simula67 conceput pentru
aplicaii n domeniul simulrii. Simula67 este primul limbaj care introduce clasa,
considerat ca fiind un grup de declaraii i proceduri luate mpreun i tratate
ca o unitate distinct de program.
Tot n aceast perioad de nceput a limbajelor de programare apare limbajul
Lisp, realizat de John McCarthy la MIT. Acest limbaj introduce un nou tip de
programare, programarea funcional. n Lisp, datele i programele sunt
reprezentate uniform sub forma expresiilor simbolice. Lisp utilizeaz forma
prefixat a operatorilor, iar structura fundamental de control este
recursivitatea. Lisp utilizeaz tehnica garbage collection n locul tergerii
explicite a referinelor. Lisp rmne n continuare n actualitate fiind puternic
aplicat n inteligena artificial, mai ales n SUA.
Un alt limbaj important a fost PL/1. El mprumut concepte de la Fortran, Cobol
i Algol68 i introduce pentru prima dat gestiunea excepiilor i multi-taskingul.
PL/1 are un rol important n descrierea paralelismului.
La sfritul anilor 60 Niklaus Wirth a realizat limbajul Pascal, urmrind
realizarea unui limbaj de programare cu numr mic de concepte integrate.
Astfel Pascal furnizeaz un mecanism de structurare a datelor, care permite un
nivel superior de abstractizare. Hoare i Wirth au oferit n 1971 definirea
axiomatic a limbajului. Limbajul Pascal permite verificarea programelor n faza
de compilare. Pe lng aceste proprieti pozitive, totui Pascal are i lipsuri,
-

COmmon Business Oriented Language, n lb. Englez

Syntactic sugar, n lb. Englez

24

Capitolul 1. Introducere n limbaje de programare

precum controlul insuficient al utilizrii pointerilor, sau anomalii n mecanismul


de definire a tipurilor. n Pascal nu se pot folosi tablouri de dimensiuni variabile,
lucru posibil n Algol68.
Anii 70 s-au caracterizat prin concentrarea eforturilor de mbuntire a stilului
de programare n limbajele imperative. Tendine majore au fost:
dezvoltarea tipului abstract de date, aprut odat cu conceptul de clas din
Simula. Tipul abstract de date a fost dezvoltat n limbajele Euclid, modula
i Ada. El este tratat din dou punte de vedere: relativ la proiectarea
limbajului de programare i ca o proprietate a limbajului n sensul unei
faciliti puse la dispoziia programatorului.
Perfecionarea mecanismelor de gestiune a excepiilor.
ncorporarea de mecanisme pentru descrierea proceselor paralele. Astfel,
s-au dezvoltat concepte precum semaforul, monitorul sau sincronizarea
prin transmitere de mesaje. Modula i Ada au faciliti pentru tratarea
concurenei.
Merit s amintim ca limbaje importante limbajul C, n care este scris sistemul
de operare Unix, i limbajul Smalltalk care marcheaz nceputul programrii
obiectuale.
Ada este un limbaj important la sfritul anilor 70. Acest limbaj a fost promovat
6
de DOD n scopul de a unifica limbajele de programare n care sunt scrise
aplicaiile militare. Ada este un limbaj de tip Pascal coninnd n plus faciliti
pentru calcule numerice, intrri/ieiri nestandard, specificarea dependenei de
main, gestiunea excepiilor, abstractizarea datelor i concuren. Proprietile
limbajului acoper toat gama conceptelor moderne de modularitate,
portabilitate, extensibilitate, abstractizare, faciliti de dezvoltare a programelor
i de ntreinere.
Anii 80 au fost marcai de dezvoltri n domeniul limbajelor pentru inteligen
artificial i a paradigmei programrii obiectuale. Astfel, apare generaia 5-a de
limbaje de programare prin Prolog, iar limbajul Smalltalk evolueaz i apare
extensia C++ a limbajului de programare C. Tot n aceast perioad se
standardizeaz o serie de limbaje de programare vechi (Fortran, Cobol i
Pascal) i apare standardul ANSI pentru C. Se dezvolt limbaje de programare
pentru manipularea datelor n aplicaii de gestiune precum dBase, FoxBase,
FoxPro, Reflex sau Paradox. Aceste limbaje au o sintax simpl i sunt
destinate cu preponderen utilizatorilor neprofesioniti. Aceast perioad este
marcat de nceputul eforturilor pentru furnizarea unor medii de programare
puternice pentru diferite limbaje. Apar mediile de programare Turbo, editoare
de texte (WordStar, WordPerfect, MicrosoftWord), editoare pentru prelucrri de

United States Department of Defense

1.3. Istoricul i evoluia limbajelor de programare

25

tabele (Lotus, Borland Quattro, Excel), pachete de proiectare asistat CAD


(AutoCAD, ORCAD) i utilitare de ntreinere.
Anii 90 sunt marcai de apariia limbajelor de programare cu traducere n dou
faze i de limbajul Java. Acesta implementeaz ntr-o manier mult mai clar i
mai concis paradigma obiectual i, prin rulare pe maina virtual Java
asigur portabilitatea programelor. n condiiile proliferrii paradigmei
obiectuale, Java s-a impus rapid, probabil i datorit dezvoltrii fr precedent
a Internetului. Totui, Java sufer la capitolul eficien la rulare, n sensul c
programele complexe Java necesit resurse de calcul i de memorie sporite
pentru o rulare eficient. Din acest punct de vedere, limbajul C++ rmne
alegerea programatorilor atunci cnd criteriul de eficien este esenial.
Succesul tehnologiilor Java, facilitile deosebite de programare pe care acest
limbaj le ofer au impulsionat productorii de limbaje de programare s-i
reconsidere oferta. Astfel, Microsoft a lansat pachetul .NET care, spre
deosebire de pachetele MSVisual ofer o tratare n 2 faze a procesului de
compilare execuie a programelor.
Tehnologia obiectual a devenit preponderent n activitatea de programare, n
strns legtur cu dezvoltarea bazelor de date relaionale i a serverelor
puternice de date. Tehnologia obiectual a fost capabil s ofere un suport
consistent acestor cerine, astfel c a reuit s se impun n dezvoltarea
aplicaiilor comerciale. Preocuparea a fost standardizarea modului de
7
dezvoltare a software-ului. Astfel, eforturile OMG sunt remarcabile, i au
8
culminat cu standardizarea specificaiilor UML pentru proiectarea obiectual.
UML este azi larg adoptat n firmele de software pentru descrierea procesului
de dezvoltare a produselor soft, n toate fazele acestuia, de la culegerea
cerinelor, analiz, proiectare, implementare pn la testare i integrarea
produsului.
n prezent tendinele dezvoltrii limbajelor de programare conduc spre
standardizarea reprezentrii cunotinelor, definirea i nglobarea n limbaj a
unui nivel semantic, utilizarea facilitilor inteligentei artificiale n realizarea
aplicaiilor curente.

1.4. ntrebri propuse


1.
2.
3.

Ce este un limbaj de programare? Descriei universul limbajelor de


programare.
Descriei cele 3 aspecte caracteristice ale unui limbaj de programare.
Descriei caracteristicile generaiilor de limbaje de programare.

Object Management Group

Unified Modeling Language

26
4.
5.
6.

Capitolul 1. Introducere n limbaje de programare

Descriei tipurile de programe de traducere.


Care sunt principiile programrii structurate?
Descriei evoluia paradigmelor de programare n ceea ce privete trecerea
de la procedur, la modul i mai apoi la obiect.
7. Descriei asemnrile i deosebirile dintre paradigma programrii
funcionale i programarea logic.
8. De ce este impropriu s considerm XML un limbaj de programare?
9. Descriei caracteristicile eseniale ale limbajelor de programare din anii 60.
10. Descriei caracteristicile eseniale ale limbajelor de programare din anii 70.
11. Descriei principalele evoluii ale limbajelor de programare n anii 80 i 90.

Capitolul 2.
Fundamentele limbajelor de programare
n acest capitol vom introduce aspectele formale ale limbajelor de programare.
Astfel, vom defini limbajele abstracte, ca i fundament pentru dezvoltarea
tehnicilor de parsare i a compilatoarelor. Seciunea 2-a a capitolului va
prezenta paii i operaiile pe care le suport un cod surs pentru a fi
transformat n cod main, prin operaia de compilare.

2.1. Limbaje abstracte


n acest capitol vom prezenta succint formalizarea exhaustiv a teoriei
limbajelor de programare. Materiale precum [Aho 1977], [erbnai 1987]
conin o tratare detaliat a acestui subiect. Teoria limbajelor de programare
este necesar pentru specificarea formal corect a limbajelor i reprezint un
fundament pentru teoria compilrii.

2.1.1. Gramatici
Fie o mulime

nevid, finit, numit alfabet. Elementele acestei mulimi se

numesc simboluri. Un simbol din A este reprezentat ntr-un limbaj printr-o


liter, cifr sau semn, uneori printr-un ir finit de litere, cifre sau semne.
Notm prin

A*

A*

pot repeta n ir. Mulimea

este un ir finit de simboluri din

A*

conine i irul vid; vom nota acest ir cu

Numrul de simboluri dintr-un ir din


observ c dac avem dou iruri

A*

obinut prin alturarea simbolurilor din


asemenea, element al mulimii
irurile

A.
A . Simbolurile se

mulimea aranjamentelor cu repetiie ale simbolurilor din

Astfel, un element din

A*.

se numete lungimea irului. Se

A*

din

atunci irul

z = xy ,

y,

va fi de

cu simbolurile din

Operaia prin care se obine irul

se numete concatenare. Mulimea

A*

din

nzestrat cu operaia

de concatenare are o structur de monoid.


Prin definiie, un limbaj formal peste alfabetul

A*.

este o submulime

a lui

28

Capitolul 2. Fundamentele limbajelor de programare

Fiind dat un alfabet

i mulimea

P ( A*)

a prilor mulimii

A * , pe aceast

din urm mulime putem defini urmtoarele operaii de baz:

L1 L2

a.

intersecie:

b.

reuniune:

c.

complementare:

d.

produs:

e.

stea:

f.

L1 L2
L = {x A* | x L}

L1 L2 = {x1 x2 | x1 L1 , x2 L2 } . Notm cu L2 = LL,...

L* = {} L L2 ... Ln ...
~ ~
~
reflectare: L = {x | x L} unde x este imaginea reflectat a lui x

n legtur cu un limbaj formal, se pune problema apartenenei unei construcii


la limbaj, adic, n condiiile furnizrii unui cuvnt
decide (demonstra) una din urmtoarele 2 concluzii:

x A * , dac se
x L sau x L .

poate

Se spune c un limbaj L este decidabil, dac rspunsul la ntrebarea de mai


sus este pozitiv.
Conceptul de algoritm st la baza rezolvrii acestei probleme. Adic, trebuie s
decidem rspunsul la ntrebarea de apartenen ntr-un timp finit folosind
operaii precis definite. Problema apartenenei unui cuvnt la limbaj, n cazul
limbajelor de programare trebuie s fie rezolvat de compilator, adic acesta
trebuie s decid dac codul surs furnizat de programator satisface sau nu
regulile limbajului, adic poate fi compilat sau nu.
n cazul n care limbajul L este finit, atunci limbajul este decidabil. Dac L
este infinit, trebuie s folosim alte metode pentru a rspunde la ntrebarea de
decidabilitate.
Specificarea limbajului nseamn fie enumerarea tuturor elementelor acestuia,
fie enunarea unor reguli de construcie a elementelor limbajului. Noiunea de
gramatic st la baza specificrii unui limbaj prin generarea tuturor cuvintelor
sale.
Prin definiie, un sistem formal este un cvadruplu ordonat
alctuit din:

alfabetul sistemului

mulimea decidabil a formulelor corecte,

mulimea decidabil a axiomelor,

F A*

S =< A, F ,, R >

2.1. Limbaje abstracte


-

29

R . O regul de deducie
n
de aritate n + 1 este o relaie din mulimea F F , care asociaz o
formul unic x cu un n-tuplu y =< y1 , y 2 ,..., y n > . Spunem c x se
mulimea finit a regulilor de deducie (inferen)

deduce din
Fie

y1 , y 2 ,..., y n

formulele

i scriem

y1 , y 2 ,..., y n ,

corecte

E0 = { y1 , y 2 ,..., y n } . Atunci, E0n


cu formule din

E0 .

yRx .
numite

premise.

Fie

reprezint mulimea tuturor n-tuplelor

Atunci, aplicnd succesiv regulile de deducie din

putem obine mulimile

Ei = Ei 1 U{x | y E ,

n
i 1 astfel incat

n 1

Dac mulimea premiselor e vid, adic


numesc teoreme. Dac

E0 =

yRx} .

atunci elementele lui

Ei

se

este o teorem, atunci ea s-a obinut prin aplicarea

Ei .

succesiv a unor reguli de deducie asupra unor formule din mulimile


Secvena acestor reguli de deducie alctuiete demonstraia teoremei

x.

Prin definiie, urmtorul caz particular de sistem formal:


a.

alfabetul

A al sistemului formal este finit i este alctuit din dou mulimi


N i , alfabetul de simboluri neterminale respective alfabetul

disjuncte
de simboluri terminale.
b.
c.
d.

F = A * : toate irurile finite pe alfabet sunt formule corecte.


conine un singur element, i anume un simbol neterminal S .

Acest
simbol se numete simbol de nceput.
Regulile de deducii au la baz producii: O producie este o pereche

( , )

de formule, notat cu

Regula de producie asociat

unei producii este o regul de rescriere, adic


i

unde

F . Aceasta nseamn c n orice formul corect

sunt 2 iruri din

care conine subirul

P Q P Q

formul corect. Notm cu

se poate nlocui

n aceste condiii, sistemul formal

cu

i se obine tot o

mulimea finit de producii.

G =< N , , P, S >

se numete gramatic.

Procesul de inferen n cazul gramaticilor se numete derivare.


Spunem despre dou iruri

din

deriveaz imediat n

cadrul unei gramatici date, dac exist dou iruri

din

i o

30

Capitolul 2. Fundamentele limbajelor de programare

producie

= 1 2

astfel nct

= 1 2 .

O asemenea

relaie de derivare reprezint o derivare ntr-un singur pas. Derivarea se poate


defini pe k pai, n cazul

este obinut din

prin k derivri.

O relaie de derivare a lui din este nebanal, dac obinerea lui se


realizeaz ntr-un numr nenul de pai. Relaia de derivare se numete
general dac se obine din
formule coincid.

ntr-un numr nenul de pai sau dac cele 2

Prin definiie, un limbaj generat de o gramatic


propoziiilor

L(G ) = {x}

cu proprietatea c

este mulimea tuturor

deriv general pe

x.

Dac limbajele generate de dou gramatici coincid, se spune c gramaticile


sunt echivalente.
Conform definiiei gramaticilor enunat de mai sus, Naom Chomsky le-a
clasificat dup forma produciilor. Astfel, avem urmtoarele tipuri de gramatici:
1. Clasa gramaticilor de tip 0: reprezint cea mai general clas de gramatici,
sunt cele care respect definiia general furnizat mai sus.
2.

Clasa gramaticilor de tip 1: produciile sunt de forma:


este un simbol neterminal,

este ir oarecare, diferit de simbolul vid.

Aceste gramatici se mai numesc i dependente de context.


3.

4.

Clasa gramaticilor de tip 2: produciile sunt de forma: A , unde A


este un simbol neterminal, este ir oarecare. Aceste gramatici se mai
numesc i independente de context.
Clasa gramaticilor de tip 3 sau regulate: produciile sunt de forma

A aB sau A a , unde A i B sunt simboluri neterminale iar a


este simbol terminal.
Corespunztor claselor de gramatici, avem clase de limbaje. Astfel, se poate
defini o ierarhie Chomsky a limbajelor.
Limbajul independent de context (de tip 2) este modelul limbajelor de
programare.
n ceea ce privete utilitatea studiului gramaticilor pentru scrierea
compilatoarelor urmtoarea teorem este important:
Orice limbaj dependent de context (i n consecin independent de context i
regulat) este decidabil. Deci, limbajele de programare sunt decidabile.

2.1. Limbaje abstracte

31

2.1.2. Specificarea limbajelor de programare


2.1.2.1. BNF
Pentru descrierea limbajelor de programare se folosesc meta-limbaje. Acestea
furnizeaz reguli prin care se pot specifica irurile acceptate de un limbaj de
programare.
BNF (Backus Naur Form) reprezint cel mai utilizat limbaj de specificare a
limbajelor de programare. n fond, BND descrie o gramatic independent de
context. n BNF, simbolurile neterminare se scriu ntre paranteze unghiulare i
se definesc recursiv, prin meta-formule. De asemenea, semnul ::= face parte
din limbajul de specificare. El se poate traduce prin: se definete astfel.
Simbolul | nseamn alegere, n sensul c permite utilizarea uneia din cele 2
alternative alturate simbolului. Astfel, n BNF, simbolurile <, >, ::=, | se
numesc meta-simboluri.
Pentru a exemplifica utilizarea BNF, vom descrie n acest limbaj de specificare
sintaxa de compunere a unei propoziii simple ntr-un limbaj informal. Astfel,
avem urmtoarea definiie BNF:
<sentence>::=<subject><verb><object>.
<subject>::=<article><noun>|<subject pronoun>
<verb>::=sees|hits
<object>::=<article><noun>|<object pronoun>
<article>::=a|the
<subject pronoun>::=he|she
<object pronoun>::=him|her

n consecin, se constat faptul c o propoziie este compus prin alturarea


unui subiect, verb i a unui obiect (atribut). Propoziia se termin cu simbolul
terminal punct. Subiectul poate fi un articol alturat unui substantiv sau
(simbolul |) un pronume de tip subiect. Pronumele de tip subiect poate fi unul
din simbolurile terminale he sau she etc.
Astfel, prin asemenea construcii se pot descrie toate regulile de producie din
limbaj. De fapt, prin BNF descriem ntreaga gramatic pe baza creia apoi,
putem genera limbajul corespunztor acesteia. Deci, pornind de la specificarea
BNF a unei gramatici, putem folosi aceast specificare pentru a genera limbajul
i pentru a recunoate sintagmele acceptate de gramatica definit.
Procesul prin care, avnd dat la intrare o propoziie, determinm (decidem)
dac propoziia respectiv este acceptabil, n contextul unei gramatici se
numete parsare.

32

Capitolul 2. Fundamentele limbajelor de programare

2.1.2.2. EBNF
De multe ori, specificarea BNF este greoaie din punct de vedere al lizibilitii,
mai ales atunci cnd un simbol neterminal se poate repeta, de un numr finit
sau infinit de ori, ntr-o construcie. De exemplu, putem considera definirea unui
string ca fiind un ir de una sau mai multe cifre:
<string>::=<digit>|<digit><string>

Pentru a uura asemenea construcii, EBNF introduce urmtoarele metasimboluri:


{}
tot ce e inclus ntre acolade se poate repeta, sau poate lipsi
[]
tot ce e inclus ntre parantezele drepte poate lipsi (este opional)
Astfel, construcia de mai sus poate fi scris:
<string>::=<digit>{<digit>}

De exemplu, pentru a defini un numr, care poate avea simbolul de semn,


putem folosi urmtoarele construcii alternative:
<numer>::=<sign><unsigned>|<unsigned>

n BNF

sau
<number>=[<sign>]<unsigned>

n EBNF

EBNF introduce i alte meta-simboluri ajuttoare. Astfel avem:


*
nlocuiete acoladele, are semnificaia c simbolul precedent se poate
repeta de un numr de 0 sau mai multe ori
+
simbolul precedent se poate repeta de 1 sau mai multe ori
_
se subliniaz meta-simbolurile, atunci cnd acestea fac parte din
alfabetul limbajului specificat

2.1.2.3. Diagrame de sintax


Reprezint o descriere alternativ vizual, a specificrii unui limbaj. Au fost
introduse la specificarea limbajului Pascal. Diagramele de sintax reprezint
grafuri orientate avnd ca noduri simbolurile din limbaj iar sgeile indic
succesiunea acceptat a acestora.
S considerm o gramatic specificat n limbaj EBNF.

2.1. Limbaje abstracte

33

<sentence>::=<expression>=
<expression>::=<number>[<operator><expression>]
<number>::=[<sign>]<unsigned>
<operator>::=*|+|-|/
<sign>::=+|<unsigned>::=<string>[.<string>]|.<string>
<string>::=<digit>{<digit>}
<digit>::=0|1|2|3|4|5|6|7|8|9

Figura 5 prezint cteva diagrame de sintax pentru elementele gramaticii de


mai sus.
<sentence>

<expression>

<digit>

0
1
2
3
4
5
6
7
8
9

<string>

Figura 5.

<digit>

Diagrame de sintax.

2.1.3. Automate de acceptare


Un automat de acceptare este folosit pentru a rspunde la ntrebarea: un ir
aparine limbajului

sau nu?

Automatul este definit ca o main cu operaii simple, care primete irul de


analizat pe un suport oarecare, l parcurge, i rspunsul final este dat de starea
n care rmne unitatea de comand a automatului. Suportul pe care este
furnizat irul este denumit generic band de intrare, iar variabila care parcurge
irul de analizat n citire se numete cap de citire. Automatul poate folosi o
memorie auxiliar pentru pstrarea unor informaii care s fie de folos la un
moment dat, n procesul decizional.

34

Capitolul 2. Fundamentele limbajelor de programare

Asemenea automate sunt definite prin grafuri. Nodurile grafului reprezint stri
ale automatului, iar arcele reprezint tranziii ntre stri. Arcele sunt marcate cu
condiii, cu semnificaia c, dac automatul se afl ntr-o anumit stare, i se
ndeplinete condiia de pe un arc care iese din starea respectiv, atunci
automatul va trece n starea de la cellalt capt al arcului selectat.
Automatele pot fi:
deterministe, dac dintr-o stare se poate realiza cel mult o singur micare
nedeterministe, dac dintr-o stare exist mai multe micri posibile.
Automatele nedeterministe corespund gramaticilor cu producii cu
alternative.
Un ir x este acceptat de un automat U dac, pornind de la configuraia
iniial, prin micrile automatului se parcurge ntregul ir de intrare i
automatul ajunge ntr-o configuraie final.
Pentru exemplificare, vom considera automatul finit din figura 6.
b
a
a
q0

q1

Figura 6.

Diagrama de tranziii a unui automat finit cu 2 stri

Astfel, automatul din figura 6 are 2 stri: q0 i q1. q0 reprezint starea iniial,
q1 reprezint starea final. Dac, pe banda de intrare se ntlnete irul a i
automatul este n starea q0, atunci automatul trece n starea q1. Dac pe
banda de intrare se ntlnete irul b i automatul este n starea q0, atunci
automatul rmne n aceeai stare etc. Tabelul 2 prezint matricea de definire
corespunztoare acestui automat.
a
b

Tabelul 2.

q0

q1

q0

q1

q1

q0

Matricea automatului din figura 6

Pentru acest automat, irul aaba este un ir acceptat deoarece:


(q0,aaba)

(q1,aba)

(q1,ba)

(q0,a)

(q1, )

Deci, pornindu-se din starea iniial q0, se parcurge irul de intrare i n final, la
epuizarea acestuia, se ajunge n starea final q1, cu irul vid

2.1. Limbaje abstracte

35

Exemplul din figura 6 reprezint un automat finit determinist. n figura 7


prezentm un exemplu de automat finit nedeterminist. Tabelul 3 reprezint
matricea de tranziii pentru acest automat. Caracteristic automatului
nedeterminist este faptul c dintr-un nod pot iei mai multe sgei etichetate cu
acelai simbol de intrare, precum i sgei etichetate cu
tranziii independente de intrare.

care reprezint

a
a

2
a

Figura 7.

Tabelul 3.

Diagrama de tranziie a unui automat finit


nedeterminist
a

{0,1}

{2}

{2,3}

{2}

{3}

Matricea automatului finit din figura 7

Se poate stabili o relaie ntre automatele finite deterministe i cele


nedeterministe. Astfel, pentru orice automat finit nedeterminist exist un
automat finit determinist care accept acelai limbaj. Vom prezenta succint n
cele ce urmeaz algoritmul de calcul al automatului finit determinist echivalent
din punct de vedere al limbajului acceptat cu un automat finit nedeterminist.
Considerm un automat finit nedeterminist care conine mulimea de stri
Fie

Q.

mulimea de simboluri de intrare acceptate de automat.

Vom construi automatul determinist cu mulimea de stri


mulime de simboluri de intrare

astfel:

Q1

pe aceeai

36

Capitolul 2. Fundamentele limbajelor de programare

Procedure AFN2AFD

Q1 {q0 }
while (mai exist stri nemarcate n

q [q1 , q2 ,..., qk ] o stare


Se marcheaz q
for a do
M 0/
For i = 1, k
M M ( qi , a )

Q1

nemarcat din

Q1

End for

q ' { p | p = ( M , )}
if

- nchiderea tranzitiv a lui

q ' Q1
Q1 Q1 {q '}

end if
La mulimea de tranziii a automatului determinist adaug
tranziia q
end for
end while
end procedure

q'

prin simbolul de intrare a

Figura 8.
Transformarea unui automat finit nedeterminist ntr-un
automat determinist echivalent din punct de vedere al limbajului
acceptat
n algoritmul din figura 8 s-au realizat urmtoarele notaii:
-

q0

reprezint starea iniial din automatul nedeterminist.

q0

este nchiderea

tranzitiv a strii iniiale.


-

(q, a )

reprezint starea care urmeaz lui q n automatul nedeterminist prin

considerarea simbolului de intrare a.


- nchiderea tranzitiv a unei mulimi de stri este mulimea tuturor strilor la
care se poate ajunge considernd stri din mulimea de intrare i tranziii doar
prin irul vid.
Algoritmul prezentat este iterativ i se bazeaz pe cutarea strilor noului
automat prin includerea de stri din vechiul automat i marcarea nodurilor deja
create. Vom exemplifica aplicarea acestui algoritm pe automatul nedeterminist
din figura 7.

2.1. Limbaje abstracte


Deci, starea iniial

q0

37
este nodul 0. nchiderea tranzitiv a acestui nod conine

nodul 0 mpreun cu toate nodurile n care se poate ajunge din acest nod
considernd doar tranziii vide. Deci

q0

este [0,2]. Acesta va reprezenta primul

nod din noul automat determinist. Marcm acest nod, i ncercm s


determinm alte noduri ale automatului determinist. Pentru aceasta vom
considera, pe rnd, fiecare simbol de intrare acceptat de automat. Fie pentru
nceput simbolul a. Construim mulimea
destinaie, pornind de la noduri din

q0

ca fiind mulimea tuturor nodurilor

i considernd tranziii acceptate de

automatul nedeterminist prin simbolul a. Obinem


nchiderea tranzitiv a lui
noduri din

M = {0,1,2} .

Considerm

, adic toate nodurile la care se poate ajunge din

prin tranziii vide succesive. Dup considerarea acestei operaii,

mulimea nou format

q'

conine aceleai noduri ca i

de noduri ale noului automat cu acest nou nod

. Extindem mulimea

q ' = [0,1,2] .

determinist adugm tranziia prin simbolul de intrare a din nodul

n automatul

q0

n nodul

q ' . Continum algoritmul prin considerarea celui de-al doilea simbol de intrare,
b. Considernd toate nodurile care urmeaz din noduri ale lui
dezvolta mulimea

M = {3} .

nchiderea tranzitiv a lui

q0

prin b, vom

este mulimea

vid. Deci, vom aduga starea mulime vid n automatul determinist i vom
lega aceast stare de starea iniial prin tranziia pe simbolul de intrare b.
Continum algoritmul prin marcarea unei noi stri,

[0,1,2] ,

i reluarea

acelorai pai. Figura 9 conine automatul finit determinist obinut.


Transformarea unui automat finit nedeterminist ntr-un automat finit determinist
este important deoarece lucrul cu automatele nedeterministe este dificil,
datorit traiectoriilor paralele pe care le poate lua calculul n aceste automate.
Dar noi trebuie s privim aceste automate n contextul studiului gramaticilor,
care definesc limbajele de programare. Astfel, pornind de la o gramatic, se
poate genera un automat finit care s accepte gramatica respectiv. Dac
automatul finit obinut pentru o gramatic este nedeterminist, vom aplica
procedura din figura 8 pentru a construi automatul finit determinist echivalent.
Automatele deterministe ne indic modul n care trebuie s tratm un ir de
intrare pentru a identifica dac acesta este acceptat sau nu de automat. Astfel,
la construirea compilatoarelor, analizorul sintactic folosete logica automatului
pentru a spune dac o construcie de intrare e valid sau nu, i n caz afirmativ,
consider mai departe aceast construcie.

38

Capitolul 2. Fundamentele limbajelor de programare

a
[2]
a

a
b
[2,3]

[0,1,2]

[0,2]

[3]
b

a,b

[0]

Figura 9.

Automatul finit determinist echivalent automatului din


figura 7.

n practic, ori de cte ori avem de implementat un parser, adic un program


care interpreteaz la intrare iruri de caractere cu anumite proprieti, prin
descrierea automatului corespunztor putem identifica traiectoriile posibile de
intrare i implementa un analizor corect i eficient. n ANSI C exist biblioteca
de expresii regulate folosite pentru generare de abloane de iruri de caractere,
care urmeaz exact regulile semantice de descriere ale automatelor.

2.2. Compilatoare
n procesul de comunicare om-calculator intervine un program intermediar,
translatorul, care asigur traducerea programelor scrise de utilizator din cod
surs ntr-un alt limbaj mai apropiat de calculator. Dac limbajul int este codul
main, translatorul se numete compilator. Astfel, execuia unui program
surs se realizeaz, n cadrul limbajelor compilative, n 2 faze:
compilare, care traduce codul surs n program obiect
execuie, care ruleaz codul obiect pe calculator, folosind datele iniiale ale
programului i produce rezultate
Compilatorul unui limbaj de asamblare se numete asamblor.
n practic, pe lng compilatoarele obinuite, exist i alte tipuri de
compilatoare.
Astfel, preprocesoarele sunt translatoare care traduc dintr-un limbaj de nivel
nalt n alt limbaj de nivel nalt. Preprocesorul limbajului C++ reprezint un bun
exemplu.

2.2. Compilatoare

39

Cross-compilatoarele sunt compilatoare scrise pentru un calculator gazd, n


vederea generrii de cod pentru alt calculator. Cross-compilatoarele sunt
folosite la scrierea de cod pentru diverse dispozitive inteligente, care conin
procesoare.
n cazul limbajelor interpretative, compilatorul este de tip special, adic
incremental. Astfel, programul surs este spart de ctre compilator n poriuni
mici numite incremente, care au o oarecare independen sintactic i
semantic. Incrementele sunt traduse de compilator. Pe msur ce
compilatorul traduce un increment, calculatorul execut incrementul tradus.
n mod tradiional, un compilator realizeaz un ir de transformri asupra
codului surs n reprezentri din ce n ce mai apropiate de codul main.
Figura 10 prezint fazele unui compilator.
Program
sursa

Sir de atomi
lexicali

Analiza
lexicala

Arbore
sintactic

Analiza
sintactica

Tratarea
erorilor

Figura 10.

Cod
intermediar

Analiza
semantica

Cod intermediar
optimizat

Optimizare
de cod

Program
obiect

Generare de
cod

Gestiunea
tabelelor

Fazele unui compilator [erbnai 1987].

Analiza lexical grupeaz caracterele din program n subiruri numite atomi


lexicali care reprezint cuvintele cheie, operatori, constante, identificatori i
delimitatori.
irul de atomi lexicali este preluat de analiza sintactic. Aceasta depisteaz
structuri sintactice cum ar fi expresii, liste, instruciuni, proceduri. Aceste
structuri sunt plasate ntr-un arbore sintactic conform relaiilor existente ntre
aceste structuri.
Analiza semantic folosete structura programului pentru extragerea
informaiilor privind obiectele purttoare de date (variabile, proceduri, funcii),
verificarea consistenei utilizrii lor. Pe msura parcurgerii arborelui sintactic,
analiza semantic construiete o reprezentare a codului surs n cod
intermediar. Acesta este de obicei un ir de instruciuni simple cu format fix.
Ordinea operaiilor din codul intermediar respect ordinea de execuie a
acestora pe calculator.
Codul intermediar este prelucrat n faza de optimizare pentru eliminarea
redundanelor de calcule, a calculelor i variabilelor inutile, pentru o execuie
mai eficient.

40

Capitolul 2. Fundamentele limbajelor de programare

Generarea de cod aloc celule de memorie pentru memorarea datelor la


execuie. Se aloc registre i se produce cod obiect echivalent cu programul n
limbaj intermediar.
Gestiunea tabelelor este de fapt, o colecie de proceduri care creeaz i
actualizeaz datele cu care lucreaz celelalte faze. n aceast tabel, pe lng
informaii proprii compilatorului se gsesc i tabele ale identificatorilor,
constantelor, cuvintelor cheie. Uneori avem o tabel unic, numit tabela
simbolurilor.
Tratarea erorilor este o colecie de proceduri care sunt activate ori de cte ori
se depisteaz o greeal n program. De obicei, utilizatorul primete un mesaj
de diagnostic. Dac greeala este identificat n faza de analiz sintactic,
compilatorul poate s-i urmeze analiza pentru a detecta i alte erori.
Structura prezentat este mai mult conceptual. Compilatoarele concrete de
multe ori prezint abateri fa de aceast structur. Unele componente pot lipsi,
sau funcionalitatea lor poate fi preluat de alte componente, sau ordinea
activrii componentelor poate fi diferit.
Realizarea compilatoarelor presupune un volum mare de munc. Exist unelte
software specializate care asigur faciliti de dezvoltare a compilatoarelor.
Astfel, avem uneltele LEX i YACC sub Unix care permit descrierea sintactic
i semantic a unui compilator, conform regulilor limbajului, utiliznd
automatele de acceptare a construciilor de intrare. Programatorul trebuie s
descrie regulile limbajului i sintaxa propoziiilor acceptate n format de expresii
regulate, iar mai apoi construcia int asociat fiecrei sintagme de limbaj
surs. Utilitarele genereaz un cod C care apoi compilat, reprezint de fapt
compilatorul pentru limbajul surs considerat.
Datele de intrare pentru asemenea unelte sunt:
specificaia limbajului surs, n ceea ce privete descrierea lexicului i a
sintaxei
specificaia limbajului int i a regulilor semantice de traducere
specificaia mainii int
Dac n trecut, timpul de elaborare a unui compilator era destul de mare, azi,
utiliznd asemenea tool-uri moderne putem realiza rapid compilatoare pentru
diverse limbaje.

2.3. ntrebri propuse


1.
2.

Descriei clasificarea gramaticilor dup Naom Chomsky.


De ce limbajul independent de context reprezint modelul unui limbaj de
programare?

2.3. ntrebri propuse


3.

4.
5.

41

Cum se specific un automat? Care sunt tipurile de automate? Explicai


importana studierii automatelor cu privire la studiul limbajelor de
programare.
Explicai structura (fazele) unui compilator. Ce se ntmpl n fiecare faz?
Se d urmtoare specificare EBNF pentru un calculator de buzunar:
(a)
(b)
(c)

<expression>::=<number>{<operator><expression>}
<sentence>::=<number>{<operator><sentence>}=
<number>::={<sin>}<unsigned>

Sunt aceste reguli de specificare corecte?


6. Fie urmtoarele producii:
<unsigned>::=<string>[.<string>]
<string>::=<digit>{<digit>}
<digit>::=0|1|2|3|4|5|6|7|8|9

Se decid care din urmtoarele numere sunt acceptate sau nu de gramatica


specificat mai sus:
(a)
1
(b)
1.
(c)
1.1
(d)
.1
(e)
12.34
7. S se scrie automatul finit determinist care accept urmtorul limbaj: {a, b,
ab, abab, }
8. Fie gramatica regulat G=<{B, S}, {a, b}, P, S> unde

P = {S , S aB, B aB, B bB, B a, B b} .

Descriei limbajul aferent acestei gramatici n BNF. Trasai automatul finit


care accept aceast limbajul asociat gramaticii. Aplicai procedura de
conversie a automatului nedeterminist n automat finit determinist i listai
automatul determinist echivalent.

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