Sunteți pe pagina 1din 19

Limbaje de programare Dorin Lixăndroiu

LIMBAJE DE PROGRAMARE

4.1. EvOLUŢIA LIMBAJELOR DE PROGRAMARE


[DODESCU 1987], *NIŢCHI 2009+, [http://....wikipedia.org/wiki/....]

Limbajele de programare sunt limbaje artificiale folosite în comunicarea dintre om şi


calculator. Evoluţia limbajelor de programare este strâns legată de evoluţia
calculatoarelor electronice şi în mod analog pot fi stabilite mai multe generaţii:

 Limbajele de generația întâia: primele calculatoare nu puteau fi programate decât în


limbaj cod-mașină (limbaj mașină); fiecare procesor are propriul cod-maşină definit de
constructorul procesorului.
 Limbajele de generația a doua: la începutul deceniului VI din secolul trecut se face
un progres remarcabil: trecerea la programarea simbolică, prin apariţia limbajelor de
asamblare; sunt considerate limbaje de nivel inferior, deoarece depind de calculatorul
pentru care sunt realizate. Apar primele elemente specifice programării simbolice:
codurile mnemonice pentru instrucţiuni şi adresarea simbolică. Au grad de portabilitate
redus.
 Limbajele de generația a treia: sunt considerate limbaje de nivel înalt (limbaje
procedurale); după apariţia în 1954 a primelor specificaţii pentru limbajul FORTRAN,
numărul limbajelor de programare creşte rapid, identificându-se în 1969 un număr de
120 de limbaje de programare, iar numai după trei ani numărul acesta ajunge la 170.
Limbajele procedurale (algoritmice) permit descrierea algoritmilor de rezolvare a
problemelor sub forma unei succesiuni de instrucţiuni care se vor executa în ordinea
stabilită de programator. Aceste limbaje pot fi folosite, teoretic, în orice problemă ce
poate fi descrisă algoritmic şi de aceea mai sunt numite şi limbaje universale.
 Limbajele de generația a patra: limbajele neprocedurale sunt considerate limbaje de
nivel foarte înalt. Aceste limbaje realizează trecerea de la prezentarea modului cum se
rezolvă problema la ce anume se doreşte. Utilizatorul prin programul neprocedural va
defini problema de rezolvat, fără a intra în detaliile specifice soluţiilor algoritmice. În
această categorie sunt incluse limbajele de interogare pentru gestiunea bazelor de date
relaţionale.
 Limbajele de generația a cincea: sunt limbajele inteligenţei artificiale. Fac parte din
această clasă limbajele logice şi limbajele de gestiune a bazelor de cunoştinţe utilizate în
realizarea sistemelor expert.

Există mai multe încercări de clasificare a limbajelor de programare. Unii autori


consideră semnificative două clase: limbajele procedurale şi limbajele neprocedurale. În
clasa limbajelor neprocedurale ar intra şi limbajele specializate (orientate pe problemă),
de exemplu limbajele de simulare (GPSS, SIMULA, SYMSCRIPT etc.). Există limbaje

1
Limbaje de programare Dorin Lixăndroiu

specializate, de exemplu: sistemele software specializate pentru calcul numeric


(MATLAB, MATHCAD, MATHEMATICA, MAPLE etc.), sistemele software specializate
pentru calcule statistice (SPSS, STATISTICA, etc.), care conţin şi elemente de limbaj
procedural prin care utilizatorul poate interveni în descrierea algoritmului de rezolvare a
problemei.

Se prezintă în continuare principalele momente istorice în apariţia limbajelor de


programare.

(1956) FORTRAN – FORmula TRANslation


Este un limbaj procedural construit pentru calcule ştiinţifice. Primul compilator
FORTRAN a fost dezvoltat pentru IBM 704 în 1954–1957 de o echipă IBM condusă de
John W. Backus. Au apărut numeroase standarde al limbajului: FORTRAN II în 1958,
FORTRAN IV în 1961, FORTRAN 66 în 1966, FORTRAN 77 în 1977 , Fortran 90 în 1990,
Fortran 95 în 1995, și Fortran 2003 în anul 2003. Cele mai recente versiuni includ suport
pentru programarea orientată obiect. Larga lui utilizare în lumea ştiinţifică a anilor 1960-
1990, datorată unor puternice biblioteci de subprograme matematice, a condus la
celebra butada “Ce nu poate fi programat în Fortran nu merită să fie programat”.

(1958) ALGOL – ALGOrithmic Language


Este un limbaj orientat pentru probleme ştiinţifice, dezvoltat de un grup al European
and American Computer Scientists, în 1958 la Universitatea Tehnică din Zürich şi are o
mare influenţă în dezvoltarea altor limbaje de programare: FORTRAN, LISP, COBOL.
Cunoaşte 3 specificaţii majore: ALGOL 58 – propus la început să se numească IAL
(International Algebraic Language), ALGOL 60 (implementat în anul 1960) şi ALGOL 68
(în anul 1968). Este primul limbaj de programare la care apare o definire riguroasă a
descrierii limbajului utilizând formalismul BNF (Backus-Naur Form).

(1960) COBOL – COmmon Business Oriented Language


Este un limbaj procedural, dezvoltat la iniţiativa comună a guvernului american şi a
sectorului privat, orientat spre probleme de gestiune economică. COBOL a fost creat
pentru a îndeplini două obiective majore: portabilitatea (capacitatea programelor a fi
utilizate pe calculatoare provenind de la producători diferiţi, necesitând modificări
minime) şi lizibilitatea (asemănarea dintre limbajul folosit de calculator şi limba engleză
propriu-zisă). Studii recente arată că limbajul de programare Cobol, în noile versiuni, ar
putea realiza o revenire importantă – în prezent există aplicaţii web scrise în Cobol şi în
viitor ar putea rezida în cloud.

(1965) PL / I – Programming Language no. I


Comapniile IBM şi Share îşi pun problema dezvoltării unui limbaj de programare care să
trateze atât probleme ştiinţifice cât şi probleme economice. Se doreşte contopirea
limbajelor FORTRAN, ALGOL şi COBOL într-unul singur care să le includă pe cât posibil.
Este un limbaj de nivel înalt, conceput să fie, pe cât posibil, independent de calculator.
Nu a avut succesul de piaţă scontat, cei care lucrau în domeniul ştiinţific nu au renunţat

2
Limbaje de programare Dorin Lixăndroiu

la FORTRAN, iar cei din domeniul economic nu au abandonat aplicaţiile funcţionale


realizate în COBOL.

(1965) BASIC – Beginner’s All purpose Symbolic Instruction Code


Creat de John G. Kemeny și Thomas E. Kurtz la Dartmouth College, limbajul BASIC este
considerat de unii autori ideal pentru începători. Nu suntem de acord cu această
afirmaţie, deoarece structurile de control existente nu permit aplicarea principiilor
programării structurate, iar folosirea în exces a instrucţiunii de salt necondiţionat GOTO
poate genera un stil de programare necorespunzător. Alte variante sunt QBasic,
GWBasic, Basic2 şi altele. O variantă evoluată de BASIC este Visual Basic, creată de către
compania Microsoft şi care se adresează programatorilor mai avansați. Limbajul Visual
Basic permite crearea de aplicații relativ complexe prin manipularea componentelor
vizuale (grafice) ale programelor.

(1971) PASCAL
Limbajul Pascal a fost dezvoltat de Niklaus Wirth de la Universitatea Tehnică din Zürich.
A fost denumit astfel în onoarea matematicianului, fizicianului şi filosofului francez
Blaise Pascal (1623-1662), care construieşte în 1642 un calculator mecanic numit
Pascaline. Limbajul Pascal permite programarea structurată, este apropiat de limbajul
natural (limba engleză) şi are o sintaxă simplă. Deoarece este foarte asemănător
limbajului algoritmic, prin formarea unui mod de gândire structurat, devine un
instrument important de comunicare în mediul universitar. Limbajul Pascal este un
limbaj de programare procedural imperativ. Cele mai populare implementări a acestui
limbaj au fost Turbo Pascal și Borland Pascal, ambele ale firmei Borland. Profesorul
Niklaus Wirth a sintetizat în următoarea ecuaţie conceptul de program scris într-un
limbaj de programare procedural imperativ : algoritmi + structuri de date = programe.

(1972) C
A fost dezvoltat în Laboratoarele Bell de către Denis Ritchie pentru a avea un limbaj
simplu și portabil pentru scrierea sistemului de operare UNIX. Limbajul operează în
strânsă legătură cu hardware-ul, fiind cel mai apropiat de limbajul de asamblare, față de
majoritatea celorlalte limbaje de programare. Sintaxa limbajului C a stat la baza multor
limbaje create ulterior: C++, Java, JavaScript.

(1979) ADA
Numele limbajului este dat în memoria primei femei programator din lume, Augusta
Ada Byron, contesă de Lovelace, fiica lordului Byron și asistenta lui Charles Babbage.
Ideea realizării acestui limbaj este dată de constatarea că în Departamentul Apărării a
SUA erau implementate în deceniul opt peste 450 de limbaje de programare, inclusiv
“dialecte” şi variante. Proiectul vast, costisitor şi ambiţios de a construi “un PL/I al anilor
’80” a condus la realizarea şi standardizarea limbajului ADA pentru a fi utilizat în
aplicaţiile software ale Penatgonului. Limbajul a fost proiectat pornind de la limbajul
Pascal, este orientat spre programare modulară, are o mare elasticitate în ceea ce
privește tipurile de date şi aduce o abordare nouă pentru tratarea excepțiilor program.

3
Limbaje de programare Dorin Lixăndroiu

Implementările pe diverse arhitecturi sunt însoțite și de instrumente de ingineria


programării. Aşteptarea ca limbajul ADA să devină unul din principalele limbaje de
programare utilizate în mod curent, la fel ca şi în cazul limbajului PL/I, nu s-a realizat.

(1983) C++
A fost realizat de Bjarne Stroustrup la Bell Labs ca o serie de îmbunătățiri ale limbajului
C. Este un limbaj procedural care permite programarea orientată pe obiecte. Devine
unul dintre cela mai populare limbaje de programare. Limbajul de programare C++ a fost
standardizat în 1998.

(1989) SQL – Structured Query Language


SQL este un limbaj de programare neprocedural bazat pe algebra relaţională, pentru
manipularea datelor în sistemele de gestiune a bazelor de date relaționale. Permite
inserarea datelor, actualizarea și ștergere, modificarea și crearea schemelor, controlul
accesului la date şi formularea interogărilor. A devenit un standard în domeniu, fiind cel
mai popular limbaj de interogare utilizat în SGBD-urile relaționale.

Din clasa limbajelor de simulare amintim:


(1961) GPSS – General Purpose Simulation System
Limbajul GPSS, realizat de Geoffrey Gordon (iniţial s-a numit Gordon's Programmable
Simulation System), permite simularea sistemelor dinamice discrete. Sistemul este
modelat cu ajutorul unor tranzacţii care trec de la un bloc la altul. Limbajul este bazat
pe ceasul simulării cu creştere variabilă, iar translatarea se face în modalitate
interpretativă. O versiune modificată este limbajul SIMUB (limbajul de SIMulare al
Universitaţii Bucureşti), realizat în cadrul Centrului de Calcul al Universităţii din Bucureşti
în anul 1977.

(1967) SIMULA – SIMulation LAnguage


A fost dezvoltat la Norwegian Computing Center din Oslo de către Ole-Johan Dahl şi
Kristen Nygaard. Iniţial, versiunea SIMULA I a fost prezentată ca o extensie a limbajului
Algol 60 pentru descrierea reţelelor de evenimente discrete. Varianta SIMULA 67
introduce conceptele de obiect, clasă, subclasă, metode virtuale, simularea
evenimentelor discrete. Limbajul SIMULA este considerat primul limbaj de programare
orientat obiect.

Din clasa limbajelor inteligenţei artificiale amintim:


(1958) LISP – LISt Processing
LISP este cel de-al doilea ca vechime limbaj de programare de nivel înalt; doar limbajul
FORTRAN este mai vechi. A fost creat la Massachusetts Institute of Technology (MIT) de
către John McCarthy. LISP este un limbaj de programare funcțional, conceput inițial ca
un model de calcul (asemănător celui construit de Turing), a devenit limbajul cel mai
folosit la crearea aplicațiilor de inteligență artificială. Programarea funcţională are la
bază pe noţiunea de funcțională sau funcție de nivel înalt, o funcție care poate accepta
ca argument sau returna ca valoare o altă funcție. Programul este văzut ca o funcţie,

4
Limbaje de programare Dorin Lixăndroiu

care se obţine din compunerea mai multor funcţii simple, fie funcţii sistem, fie definite
de utilizator.

(1973) PROLOG – PROgramming LOGical


Limbajul PROLOG este un limbaj specific inteligenței artificiale. A fost realizat la
Universitatea din Marsilia de Alain Calmaureur. Este utilizat la demonstrarea automată a
teoremelor, realizarea sistemelor expert şi a jocurilor.

Din clasa sistemelor software specializate pentru calcul numeric amintim:


(1979) MATLAB - MATrix LABoratory
MATLAB este un mediu de dezvoltare pentru calcul numeric și analiză statistică
dezvoltat iniţial de Cleve Moler de la Universitatea din New Mexico. Limbajul permite
lucru cu matrice, reprezentări grafice în 2-D şi 3-D, implementarea algoritmilor,
realizarea de calcule simbolice. Un pachet adițional, Simulink, oferă posibilitatea de a
realiza modele matematice de simulare pentru sistemele dinamice.

(1986) MATHCAD – MATHematics Computer Aided Design


MathCAD este un produs software al firmei MathSoft Inc., Cambridge, Massachusetts
realizat de Allen Razdow de la Massachusetts Institute of Technology (MIT) şi cofondator
al firmei MathSoft. Este un produs de tipul CAD (Computer Aided Design) destinat
rezolvării problemelor de calcul numeric cu aplicaţii în cele mai variate domenii.
Versiunile mai noi permit şi realizarea de calcule simbolice.

Limbajele apărute după 1990, sunt în general legate de dezvoltarea noilor tehnologii
web, a aplicaţiilor pe Internet.

(1995) JAVA
Java este un limbaj de programare orientat-obiect. A fost dezvoltat de către James
Gosling la Sun Microsystems (în prezent filială Oracle). În Java sunt realizate multe
aplicaţii web, iar noile evoluţii tehnologice permit utilizarea sa şi pe dispozitivele mobile.
Un program Java compilat, corect scris, poate fi rulat fără modificări pe orice platformă
pe care este instalată o mașină virtuală JVM (Java Virtual Machine). Are un mare nivel
de portabilitate datorită modalităţii de translatare în două faze, care va fi prezentată în
paragraful următor.

ASP - Active Server Pages


ASP este un limbaj de programare folosit pentru a construi site-uri web cu conţinut
dinamic, putând interacţiona cu diferite baze de date. ASP este dezvoltat de Microsoft şi
este legat de sistemul Windows şi de serverul web Microsoft Internet Information
Services Web Server (IIS). Se prezintă ca o tehnologie foarte bine suportată, bazându-se
pe comunitatea de dezvoltatori Microsoft. ASP este gratuit numai dacă este folosit un
server Windows care are deja liceanţă.

5
Limbaje de programare Dorin Lixăndroiu

PHP - Personal Home Pages


PHP, la fel ca şi ASP, este un limbaj de programare folosit pentru a construi site-uri web
cu conţinut dinamic, ce pot interacţiona cu diferite baze de date. PHP a fost creat de
Rasmus Lerdorf şi poate funcţiona atât pe servere Unix şi Linux cât şi pe sisteme
Microsoft. Limbajul are o mare popularitate printre programatori, prin sintaxa relativ
simplă, un set foarte mare de funcţii şi prin faptul că este complet gratuit. Este portabil
pe orice platformă. Se integrează cu toate serverele web indiferent de sistemul de
operare utilizat.

(1989) HTML – Hyper Text Markup Language


HTML nu este un limbaj de programare. HTML este un limbaj universal de marcare a
textului, interpretat de browsere şi se foloseşte pentru elaborarea diferitelor
documente text cu linkuri şi elemente multimedia – pagini web, prezentări etc. Este
dezvoltat de Tim Berners-Lee la CERN (Centrul European de Cercetări Nucleare de la
Geneva) pentru facilitarea accesului rapid la informaţiile tehnice cuprinse în manualele
de utilizare a calculatoarelor. Un document HTML este un fişier text (ASCII) care conţine
descrieri recunoscute de programele de navigare pe Internet. Aceste fişiere pot fi create
utilizând orice editor de texte, afişate şi modificate pe orice calculator cu orice sistem de
operare.

4.2. REZOLVAREA UNEI PROBLEME CU CALCULATORUL


[LIVOVSCHI 1981], *NIŢCHI 2009], *ŞERBĂNAŢI 1987]

Rezolvarea unei probleme cu calculatorul presupune adaptarea algoritmului de


rezolvare a problemei sub forma unor comenzi sau indicaţii transmise spre execuţie
calculatorului. Descrierea succesiunii acestor operaţii care reprezintă procesul de calcul
se numeşte program. Prin program este transmis calculatorului algoritmul de rezolvare
al problemei. Limbajul de programare descrie regulile de realizare ale unui program.

Limbajul de programare apare ca un intermediar între sistemul real în care a apărut


problema de rezolvat şi sistemul de calcul. În această idee, fiecare element al limbajului
de programare trebuie văzut simultan din două puncte de vedere:
- logic (punctul de vedere al problemei), adică ce reprezentăm din problemă cu
ajutorul elementului din limbaj;
- fizic (punctul de vedere al implementării), adică ce realizează calculatorul la
execuţia elementului din limbaj.

Pentru rezolvarea unei probleme cu calculatorul se construieşte un model care apoi va fi


simulat pe calculator. Ce cuprinde acest proces este redat schematic în figura de mai jos:

6
Limbaje de programare Dorin Lixăndroiu

Problema

modelare

Algoritmul
problemei

limbaj de programare

Program

Figura 4.1. De la problemă la program

Utilizarea unui program scris într-un limbaj de programare de nivel înalt devine posibilă
prin activarea unui program de translatare (program de traducere) care traduce şi
converteşte în una sau mai multe etape programul iniţial, într-un limbaj de nivel inferior
acceptat de calculatorul pe care se doreşte execuţia programului.

Translatarea se poate realiza în 3 moduri:


 modalitatea compilativă – translatarea este efectuată înaintea execuţiei de un
program specializat numit compilator; programul scris în limbaj sursă
(program sursă) este tradus într-un program obiect echivalent cu cel
iniţial ce poate fi executat direct de procesor. Avantaj: execuţie rapidă.
Dezavantaj: programul obiect (executabil) obţinut în urma compilării într-
un format de nivel scăzut (cod maşină) nu poate fi rulat decât pe
platforma pe care a fost compilat.
Exemple de limbaje cu compilator: Pascal, C,...
 modalitatea interpretativă - translatarea este efectuată în cursul procesului de
execuţie de un interpretor. Fiecare instrucţiune din programul sursă este
interpretată (tradusă) şi executată. De exemplu, în cazul unei instrucţiuni
de ciclare interpretarea este repetată la fiecare reluare a ciclului. Avantaj:
simplitate. Dezavantaj: viteza de execuţie redusă.
Exemplu de limbaj cu interpretor: Basic.
 modalitatea translatării în două faze – în prima fază programul sursă este tradus
într-un cod intermediar (cod de octeţi) care apoi este rulat pe o maşină
virtuală. Prima fază corespunde compilării, iar cea de-a doua fază
corespunde interpretării codului de octeţi generat care este asemănător
codului scris într-un limbaj de asamblare. De aici, avantajul acestui cod
care este interpretat în mediul de execuţie al limbajului de programare şi
poate fi rulat pe orice platformă care foloseşte acest mediu.

7
Limbaje de programare Dorin Lixăndroiu

Exemplu de limbaj cu translatare în două faze (compilare şi interpretare):


Java cu mediu de execuţie maşina virtuală Java (JVM). JVM interpretează
codul precompilat şi îl va rula sub forma unei aplicaţii.

Pentru a înţelege semnificaţia termenilor utilizaţi în continuare şi a legăturii limbaj


natural – limbaj de programare (limbaj artificial), reamintim câteva definiţii legate strict
de studiul limbajelor naturale (conform Dicţionarului encicopedic, Editura Enciclopedică,
Bucureşti, 1993-2009):

Gramatică – disciplină a lingvisticii al cărei obiect de studiu îl constituie structura


gramaticală a unei limbi date; ansamblu de reguli privitoare la modificarea
formei cuvintelor şi la îmbinarea lor în propoziţii şi fraze.
Lexic – vocabular.
Vocabular – totalitatea cuvintelor unei limbi.
Semantică – ramură a lingvisticii care studiază sensurile cuvintelor şi evoluţia acestor
sensuri.
Sintactică – (adjectiv) privitor la sintaxă, care aparţine sintaxei.
Sintaxă – parte a gramaticii care studiază funcţiile cuvintelor şi ale propoziţiilor în
vorbire şi care stabileşte regulile de îmbinare a cuvintelor în propoziţii şi a
propoziţiilor în frază.

4.3. COMPILATOARE
[LIVOVSCHI 1981], *NIŢCHI 2009+, *ŞERBĂNAŢI 1987+, [VAIDA 1976]

În cazul existenţei unui program de translatare (compilator) execuţia unui program scris
în limbaj de programare (program sursă) presupune într-o primă etapă compilarea
programului, urmată de lansarea în execuţie.

Datele de intrare

Program Compilator Program Rezultate


sursă obiect

Figura 4.2. Execuţia unui program în modalitate compilativă

Compilatorul este un program complex, care realizează printr-un şir de transformări


succesive trecerea programului sursă în program obiect.

8
Limbaje de programare Dorin Lixăndroiu

Pentru a înţelege conceptul de compilator şi fazele procesului de compilare, definim:


entitatea (token) - o succesiune de simboluri, utilizate în scrierea programelor sursă şi
căreia i se asociază o definiţie sintactică. Informaţia relativă la entităţile unui program
este memorată sub forma unor tabele în care apare tipul entităţii, denumirea în
program a entităţii, adresa (pointer). În limbajele de programare se consideră entităţi:
identificatorii, constantele, cuvintele cheie, operatorii etc.

În Figura 4.3. se prezintă modelul unui compilator, din care rezultă fazele procesului de
compilare.
1) Analiza lexicală este realizată de analizorul lexical, parte a compilatorului, care
admite la intrare şirul simbolurilor din programul sursă şi produce la ieşire un şir
de entităţi.
2) Analiza sintactică este realizată de analizorul sintactic, parte a compilatorului,
care admite la intrare şirul entităţilor furnizate de analizorul lexical şi produce la
ieşire o reprezentare a structurii sintactice (expresii, liste, instrucţiuni, proceduri
etc.). Structurile sintactice identificate sunt plasate într-un arbore sintactic, care
reflectă relaţiile existente între structuri. Analiza sintactică verifică dacă şirul
entităţilor este corect, în sensul respectării definiţiilor sintactice.
3) Analiza semantică este realizată de generatorul de cod, parte a compilatorului,
care admite la intrare reprezentarea structurii sintactice a programului sursă.
Prin parcurgerea arborelui sintactic se extrag informaţii privind apariţia
obiectelor purtătoare de date din program (ex. variabile, proceduri etc.) şi se
verifică consistenţa utilizării lor. Se obţine o translatare a programului sursă în
cod intermediar, care este o succesiune de instrucţiuni simple direct executabile
de calculator.
4) Optimizarea codului este realizată de optimizator, parte a compilatorului, care
admite la intrare forma în cod intermediar a programului sursă şi produce la
ieşire o transcriere eficientă a acestuia. Optimizarea constă în eliminarea
redundanţelor, a calculelor şi variabilelor inutile în scopul unei execuţii mai
eficiente prin reducerea memoriei ocupate şi a timpului de execuţie.
5) Generarea codului este realizată de asamblor, parte a compilatorului, care
admite la intrare transcrierea eficientă a programului sursă translatat şi produce
la ieşire programul obiect (forma direct executabilă).
6) Gestiunea tabelelor este o colecţie de proceduri ce crează şi actualizează baza
de date cu care se lucrează ăn diferitele faze ale compilării.
7) Analiza erorilor este o colecţie de proceduri care sunt activate în momentul
apariţiei unei erori în program. În urma detectării sunt transmise utilizatorului
mesaje de eroare pentru a efectua corecţiile necesare.

9
Limbaje de programare Dorin Lixăndroiu

Programul sursă

Analiza lexicală

Şir de entităţi
Analiza
Analiza sintactică
erorilor
Arbore sintactic
Gestiunea
tabelelor Analiza semantică

Cod intermediar

Optimizarea de cod

Generarea de cod

Programul obiect

Figura 4.3. Modelul unui compilator

Observaţie. Modelul de compilator prezentat este o structură conceptuală.


Compilatoarele existente pot prezenta abateri de la acest model, în sensul că unele
componente pot lipsi, funcţiile lor fiind preluate de alte componente.

4.4. ELEMENTE DE TEORIA LIMBAJELOR FORMALE


[AHO 1986+, *CREANGĂ 1974+, *LIVOVSCHI 1981+, *NIŢCHI 2009+, [ORMAN 1982],
*ŞERBĂNAŢI 1987+, *VAIDA 1976+

Teoria limbajelor formale stă la baza definirii limbajelor de programare şi construcţiei


compilatoarelor.
Considerăm o mulţime finită şi nevidă V, numită alfabet. Elementele acestei mulţimi se
numesc simboluri. Notăm cu N  0 ,1,2 ,... mulţimea numerelor naturale.
Definiţia 4.1. Numim cuvânt peste alfabetul V orice element al mulţimii V    V k .
kN

V reprezintă vocabularul, adică mulţimea tuturor cuvintelor pe V. Orice cuvânt
x  a1a2 ...ak V k , va fi notat a1a2 ...ak , iar k reprezintă lungimea cuvântului, adică
numărul de simboluri din cuvânt. Notăm cu x lungimea cuvântului x. Mulţimea V 0 are

10
Limbaje de programare Dorin Lixăndroiu

un singur cuvânt, notat cu e şi numit cuvântul vid. Lungimea cuvântului vid este 0
( e  0 ). Notăm cu V   V   e .
Exemplu. Dacă V  a , b , atunci V 0  e, V 1  a , b, V 2  aa , ab , ba , bb,....
Definiţia 4.2. Dacă a1a2 ...ar şi b1b2 ... bp sunt două cuvinte, funcţia c : V   V   V 
 
definită prin c a1a2 ...ar , b1b2 ... bp  a1a2 ...ar b1b2 ... bp se numeşte operaţie de
concatenare. Avem evident xy  x  y . Cuvântul vid este elementul neutru pentru
operaţia de concatenare.
Definiţia 4.3. Un limbaj formal L este o mulţime de cuvinte pe un alfabet V, adică
L  V* .

Pentru un limbaj formal, problema apartenenţei unui cuvânt la limbaj este esenţială şi
se defineşte astfel: dat cuvântul x V , se poate decide dacă x  L sau x  L ? Dacă DA
spunem că L este decidabil.
Tradus în termenii unui limbaj de programare problema apartenenţei constă în a decide
dacă un şir de simboluri din alfabetul limbajului formează un program corect sau nu.
Această problemă trebuie rezolvată de orice compilator.

Pentru a studia un limbaj acesta trebuie specificat într-un anumit mod. Dacă limbajul L
este finit, specificarea se poate face prin enumerarea tuturor cuvintelor limbajului şi
atunci, evident, problema apartenenţei unui cuvînt la limbaj este rezolvată – L este
decidabil.
Dacă L este infinit studiul limbajului presupune definirea unor proprietăţi a cuvintelor şi
reguli de formare a lor. În acest caz, o metodă de a reprezenta limbajul L este sistemul
generator numit gramatică. Orice cuvânt din L se poate construi prin metode bine
definite, folosind regulile gramaticii, numite şi producţii.

O gramatică G pentru un limbaj L foloseşte două mulţimi finite şi disjuncte de simboluri:


VT - simboluri terminale (ireductibile), care reprezintă chiar alfabetul V pe care L este
definit;
VN - simboluri neterminale (variabile sintactice), care vor fi folosite în procesul de
generare a cuvintelor limbajului.
O producţie (regulă de deducţie) este o pereche ordonată  ,   unde:
  VN  VT VN VN  VT  , α conţine cel puţin un simbol neterminal;
  VN  VT  reprezintă un cuvânt din vocabularul total al limbajului.
Notăm o producţie    şi spunem “  derivă din  ” sau “  generează pe  ”.
Procesul prin care se aplică regulile de deducţie se numeşte derivare.

Definiţia 4.4. O gramatică G este un sistem G  VN ,VT , S , P  , unde:


VN - mulţimea simbolurilor neterminale;
VT - mulţimea simbolurilor terminale;

11
Limbaje de programare Dorin Lixăndroiu

S – simbolul de start al gramaticii S VN  ;


P – mulţimea finită de producţii (reguli de rescriere) de forma  ,   .

Exemplu. Gramatica G este definită astfel:


G  S , X ,Y ,a , b , c , d, S , P 
unde: VN  S , X ,Y 
VT  a , b , c , d
S VN este simbolul de start
P  S  XY , X  a , X  b ,Y  c ,Y  d .

Relaţiile de derivare directă pot fi extinse la relaţii de derivare în k paşi.


k
Notăm    o derivare de lungime k, formată dintr-un şir de derivaţii:
   1 ,  1   2 ,....,  k1  

Notăm cu    relaţia de derivare generală, care spune că în gramatica G, α
G
generează pe β (sau β derivă din α) în k  1 paşi.

Definiţia 4.5. Numim forme propoziţionale şirurile derivate din simbolul de start (S) al
gramaticii. Formele propoziţionale alcătuite numai din simboluri terminale se numesc
propoziţii.

Definiţia 4.6. Fie gramatica G  VN ,VT , S , P  . Limbajul generat de gramatica G este
  
format din mulţimea propoziţiilor LG   w | S  w  . Două gramatici sunt echivalente,
 G 
dacă generează acelaşi limbaj.

Observaţii. Limbajul generat de o gramatică G este format numai din propoziţii care
conţin simboluri din alfabetul terminal VT . Propoziţiile sunt derivabile din simbolul de
start (S).

Exemplu. Fie gramatica G este definită astfel:


G  S,a , b, S , P 
unde: VN  S
VT  a , b
S VN este simbolul de start
P  S  aSb , S  ab .
O propoziţie care aparţine lui L(G) este:
3
S  aSb  aaSbb  aaabbb  a 3 b 3 sau notat altfel: S  a 3 b 3

Se poate demonstra că limbajul generat de această gramatică este LG   a n b n | n  1 . 

12
Limbaje de programare Dorin Lixăndroiu

Noam Chomsky introduce în 1959, o clasificare a gramaticilor după forma producţiilor:


tipul 1 – gramatici dependente de context, tipul 2 - gramatici independente de context,
tipul 3 – gramatici regulate. Corespunzător acestor tipuri de gramatici avem clasele
limbajelor generate.

Definiţia 4.7. O gramatică G  VN ,VT , S , P  se numeşte independentă de context


(context free) dacă fiecare producţie este de forma A   cu AVN şi   VN  VT  .
Limbajul independent de context, generat de o gramatică independentă de context,
reprezintă modelul utilizat în definirea limbajelor de programare. Se demonstrează că
orice limbaj independent de context este decidabil.

Concluzii. În sensul celor prezentate mai sus putem spune că un program scris într-un
limbaj de programare este o propoziţie corectă pe un vocabular. Limbajul de
programare conţine o mulţime infinită de propoziţii, care sunt programele realizabile în
acest limbaj. Gramatica limbajului conţine regulile care stabilesc modul de construcţie a
propoziţiilor limbajului, adică regulile care ne permit scrierea programelor.

În general o formă propoziţională poate fi obţinută prin mai multe derivări, considerate
echivalente. Numim derivare stânga, derivarea în care se înlocuieşte la fiecare pas cel
mai din stânga simbol neterminal. Analog, derivarea dreapta se obţine înlocuind la
fiecare pas cel mai din dreapta simbol neterminal.

Exemplu. Fie gramatica G este definită astfel:


G  S,a , , ,( , ) , S , P 
unde: VN  S
VT  a , , ,( , ) 
S VN este simbolul de start
P  S  S  S , S  S  S , S  S , S  a .
Propoziţia a  a  a L( G ) poate fi obţinută, plecând de la simbolul de start, în două
moduri:
- derivare stânga:
S  S  S  a  S  a  S   a  S  S   a  a  S   a  a  a
- derivare dreapta:
S  S  S  S  S   S  S  S   S  S  a  S  a  a  a  a  a

Reprezentarea grafică a derivării poate fi făcută cu ajutorul arborilor de derivare.

Definiţia 4.8. Un arbore de derivare pentru o gramatică G  VN ,VT , S , P  independentă


de context este un arbore aşezat pe niveluri, în care fiecare vârf este etichetat cu
elemente din VN  VT , astfel încât:
a) radăcina arborelui este etichetată cu S ;

13
Limbaje de programare Dorin Lixăndroiu

b) vârfurile interioare (care au descendenţi) sunt etichetate cu simboluri


neterminale ale gramaticii, iar vârfurile terminale (frunzele) sunt etichetate cu
simboluri terminale;
c) pentru orice vârf interior A având descendenţii direcţi etichetaţi  1 , 2 ,..., k ,
există o producţie în P de forma: A   1 2 ... k .
Şirul simbolurilor care etichetează frunzele arborelui scrise în ordine de la stânga la
dreapta formează frontiera arborelui.

Pentru propoziţia din exemplu anterior a  a  a L( G ) arborele de derivare este dat în
Figura 4.4.
S

S S
x
S S
( )
a
S
S S
+
+
S
a a
S
Figura 4.4. Arborele de derivare

Observăm că frontiera arborelui din Figura 4.4. reproduce propoziţia a  a  a L( G ) .


Aplicaţie
Fie gramatica independentă de context G  VN ,VT , S , P  , unde:
unde: VN  S , A , B
VT  a , , ,( , ) 
S VN este simbolul de start
P conţine următoarele producţii (reguli de rescriere):
(1) S  S  A
(2) S  A
(3) A  A  B
(4) A  B
(5) B  S 
(6) B  a
Cu ajutorul acestei gramatici având ca operand a şi operatori +, x, ( , ) se pot genera
expresii aritmetice. Acestea constituie L(G), limbajul generat de gramatica G.

14
Limbaje de programare Dorin Lixăndroiu

a) Considerăm propoziţia:
a  b  a  a
Acest program aparţine lui L(G)? Răspunsul este negativ, deoarece simbolul bVT . Un
compilator construit pentru acest limbaj va semnala eroare în faza de analiză lexicală.

b) Fie acum propoziţia:


a  a  a  a  a
Acest program aparţine lui L(G)? Compilatorul construit pentru acest limbaj parcurge
faza de analiză lexicală fără erori, deoarece toate simbolurile utilizate aparţin lui VT .
În faza de analiză sintactică pornind de la simbolul de start S, aplicând regulile gramaticii
încercăm să obţinem propoziţia. Exemplificăm aplicând derivări la stânga (cifrele de sub
simbolul de derivare indică regula de rescriere aplicată).

S  S  A  A  A  B  A  a  A  a  A  B  a  B  B  a  a  B  a  a  S  
( 1) ( 2) ( 4) (6) ( 3) ( 4) (6) ( 5) ( 1)
a  a  S  A  a  a  A  A  a  a  B  A  a  a  a  A  a  a  a  A  B 
( 2) ( 4) (6) ( 3) ( 4)
a  a  a  B  B  a  a  a  a  B  a  a  a  a  a  .
(6) (6)
Rezultă că propoziţia a  a  a  a  a LG  şi deci faza de analiză sintactică a fost
parcursă fără eroare.

Analog, aplicând derivări la dreapta obţinem:


S  S  A  S  A  B  S  A  S   S  A  S  A  S  A  S  A  B 
( 1) ( 3) ( 5) ( 1) ( 3) (6)
S  A  S  A  a  S  A  S  B  a   S  A  S  a  a  S  A  A  a  a 
( 4) (6) ( 2) ( 4)
S  A  B  a  a  S  A  a  a  a  S  B  a  a  a   S  a  a  a  a 
(6) ( 4) (6) ( 2)
A  a  a  a  a  B  a  a  a  a   a  a  a  a  a  LG .
( 4) (6)

Problema realizării analizei sintactice revine la definirea unui algoritm care să decidă
dacă o propoziţie aparţine sau nu limbajului generat de gramatica G. Un astfel de
algoritm poate fi privit ca o maşină cu operaţii simple, care primeşte la intrare şirul
simbolurilor de analizat (care constituie programul sursă), îl parcurge secvenţial şi în
final prin starea în care rămâne stabileşte dacă şirul a fost acceptat sau nu. Structura
matematică folosită pentru recunoaşterea (acceptarea) unui program ca aparţinând
limbajului de programare în care a fost realizat se numeşte automat de acceptare.

Pentru a crea o imagine asupra modului de lucru al compilatorului, prezentăm fazele


parcurse pentru translatarea unei instrucţiuni simple de atribuire.

15
Limbaje de programare Dorin Lixăndroiu

valoare := avans + rata x 12

Analiza lexicală

id1 := id2 + id3 x 12

Analiza sintactică

:=
Id1 +
= Id2 = x
:= Id3 12
2:
=
Analiza semantică

:=

Tabela informaţii +
Id1
= x
valoare ....... Id2
avans ....... :=
Id3 int-to-real
rata ....... 2:
=
12

Generarea codului
intermediar

temp1 := integer-to-real (12)


temp2 := id3 x temp1
temp3 := id2 + temp2
id1 := temp3

Optimizarea codului

temp1 := id3 x 12.0


id1 := id2 + temp1

16
Limbaje de programare Dorin Lixăndroiu

Generarea codului

MOVE id3, R2
MULTIPLY 12.0, R2
MOVE id2, R1
ADDITION R2, R1
MOVE R1, id1

Comentarii.
 Analiza lexicală - se parcurge şirul simbolurilor din instrucţiunea de atribuire şi se
constată că din punct de vedere lexical instrucţiunea este corectă, se găseşte un
şir de entităţi format din 3 identificatori (id1, id2, id3) şi o constantă (12).
 Analiza sintactică pleacă de la şirul entităţilor furnizate de analizorul lexical şi
produce o reprezentare a structurii sintactice sub formă de arbore de derivare (o
reprezentare grafică a derivării). Se constată că şirul entităţilor este corect, în
sensul respectării definiţiei sintactice de construcţie a unei instrucţiuni de
atribuire, cu alte cuvinte, instrucţiunea de atribuire este corectă.
 Analiza semantică impune schimbarea reprezentării întregi a valorii 12 în
formatul de reprezentare a numerelor reale. Se realizează prin funcţia de
conversie int-to-real (integer to real). Această conversie este necesară pentru a
putea evalua o expresie de forma: real := real x real.
 Generarea codului intermediar presupune execuţia secvenţei:
temp1 := integer-to-real (12)
temp2 := id3 x temp1
temp3 := id2 + temp2
id1 := temp3
unde temp1, temp2, temp3 sunt variabile temporare.
Se obţine: temp1 ← 12.0
temp2 ← rata x 12.0
temp3 ← avans + temp2 (← avans + rata x 12.0)
id1 ← temp3 (← avans + rata x 12.0)
 Optimizarea codului presupune o analiză a secvenţei generate anterior. Se
observă că numărul de atribuiri poate fi redus.
Se obţine: temp1 := id3 x 12.0
id1 := id2 + temp1
adică: temp1 ← rata x 12.0
id1 ← avans + rata x 12.0

17
Limbaje de programare Dorin Lixăndroiu

 Generarea codului presupune o transcriere eficientă a programului sursă


translatat.
Se obţine secvenţa: MOVE id3, R2
MULTIPLY 12.0, R2
MOVE id2, R1
ADDITION R2, R1
MOVE R1, id1
care impune utilizarea a 2 regiştri, R1 şi R2, pentru efectuarea operaţiilor.

Operaţiile din secvenţă trebuie interpretate astfel:


MULTIPLY operand2, operand1
presupune efectuarea inmulţirii: operand1 x operand2
şi apoi rezultatul este depozitat în: operand1

ADDITION operand2, operand1


presupune efectuarea adunării: operand1 + operand2
şi apoi rezultatul este depozitat în: operand1

MOVE operand2, operand1


presupune transferul operand2 în operand1.

Revenim la secvenţă şi obţinem în urma execuţiei:


R2 ← rata
R2 ← R2 x 12.0 (← rata x 12.0)
R1 ← avans
R1 ← R1 + R2 (← avans + rata x 12.0)
id1 ← R1 (← avans + rata x 12.0)
adică evaluarea instrucţiunii de atribuire:
valoare := avans + rata x 12

18
Limbaje de programare Dorin Lixăndroiu

Bibliografie

[AHO 1986] Aho A.V., Sethi R., Ullman J.D., Compilers: Principles, Techniques, and Tools,
Addison Wesley, Pearson Education, Inc., 1986.
[BARBU 1997+ Barbu Ghe., Văduva I., Boloşteanu M., Bazele informaticii, Ed. Tehnică,
Bucureşti, 1997.
[CREANGĂ 1974+ Creangă I., Reischer C., Simovici D., Introducere algebrică în
informatică. Limbaje formale, Editura Junimea, Iaşi, 1974.
[DODESCU 1987] Dodescu Ghe., Informatica, Ed. Ştiinţifică şi Enciclopedică,
Bucureşti, 1987.
[LIVOVSCHI 1981+ Livovschi L., Popovici C., Georgescu H., Ţăndăreanu N., Bazele
informaticii, Ed. Didactică şi Pedagogică, Bucureşti, 1981.
[LIXĂNDROIU 2000+ Lixăndroiu D., Bazele informaticii economice, Editura Infomarket,
Braşov, 2000.
[NIŢCHI 1996+ Niţchi Ş., Racoviţan D. şi alţii, Bazele prelucrării informaţiilor şi tehnologie
informaţională, Ed. Intercredo, Deva, 1996.
*NIŢCHI 2009+ Niţchi Ş. (coord.), Elemente avansate de informatică economică, Editura
Risoprint, Cluj-Napoca, 2009.
[ORMAN 1982] Orman G., Limabje formale, Editura Tehnică, Bucureşti, 1982.
*ŞERBĂNAŢI 1987+ Şerbănaţi L.D., Limbaje de programare şi compilatoare, Editura
Academiei, Bucureşti, 1987.
[VAIDA 1976] Vaida D., Limbaje formale şi tehnici de compilare, Universitatea din
Bucureşti, 1976.

19

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