Forma de Învățământ : zi [632253]

0
Universitatea din Oradea
Facultatea de Ingineri e Electrică și Tehnologia
Informaț iei
Programul de studiu: Calculatoare
Forma de Învățământ : zi

PROIECT DE
DIPLOM Ă

Coordonator științific :
Conf. dr. ing Ovidiu Constantin Novac Absolvent: [anonimizat]-Andrei Luka

Oradea
2018

1
Universitatea din Oradea
Facultatea de Inginerie Electric ă si Tehnologia
Informaț iei
Programul de studiu: Calculatoare
Forma de Învățământ : zi

Analizor Lexical în
Java

Coordonator științific :
Conf. dr. ing Ovidiu Constantin Novac Absolvent: [anonimizat]-Andrei Luka

Oradea
2018

2

Cuprins
Capitolul I. Introducere ………………………….. ………………………….. ………………………….. ………….. 3
Capitolul II. Noțiuni generale ………………………….. ………………………….. ………………………….. …. 4
II.1 Compilatorul ………………………….. ………………………….. ………………………….. ……………….. 6
II.2 Limbajul JAVA ………………………….. ………………………….. ………………………….. …………… 8
II.3 Noțiunea generală de limbaj ………………………….. ………………………….. …………………….. 14
Capitolul III Limbaje regulate si automate finite ………………………….. ………………………….. ….. 16
III.1 Limbaje regulate și expresii regulate ………………………….. ………………………….. ……….. 17
III.2 Sisteme tranziționale ………………………….. ………………………….. ………………………….. …. 18
III.3Analiza lexicală ………………………….. ………………………….. ………………………….. …………. 20
III.4Analizorul lexical pentru limbajul Java ………………………….. ………………………….. …….. 23
Capitolul IV Descrierea aplicatiei software ………………………….. ………………………….. …………. 29
Capitolul V Concluzii ………………………….. ………………………….. ………………………….. ………….. 35
Biblio grafie ………………………….. ………………………….. ………………………….. ………………………… 36

3

Capitolul I. Introducere

Această lucrare are ca și obiectiv principal ilustrarea importanței procesului de analiză
lexicală.
Am ales această tematica pentru a descoperi și învăța cât mai multe despre Java.
Vom explica noțiuni generale care aparțin domeniului precum noțiunea de compilator,
limbaj, analiză lexicală, dar și specializate precum expresii regulate, sistem tranzițional.
Sunt incluse și informații despre limbajul de programare Java .
Această lucrarea ilustrează analiza lexicală generală dar și din punct de vedere al
limbajului de programare Java. Se va pune foarte mult acce ntul pe exemple relevante Java.
Versi unea d e Java studiata este SE 7 .
Vom ilustra și pașii necesari pentru crearea unei aplicații de analiză lexicală .
Programul analizează un fișier de intrare și afișează valoarea semantică și lexicală a unităților
detectate .

4

Capitolul II . Noțiuni generale

Un limbaj de programare este un limbaj care are drept scop descrierea unor procese de
prelucrare a anumitor date și a structurii acestora care se realizează în general cu ajutorul unui
sistem de calcul.Limbajele se pot clasifica în limbaj e de nivel superior sau inferior.
Există în prezent un număr mare de limbaje de programare de nivel înalt sau evoluate
care se caracterizează printr -o anumită naturalețe, în sensul că descrierea procesului de
prelucrare cu ajutorul limbajului este apropiat ă de descrierea naturală a procesului
respectiv.Dintre limbajele de acest tip cu o anumită răspândire în momentul de față
menționăm limbajul JAVA. Precizăm că delimitarea domeniului de aplicabilitate al unui
limbaj de programare nu are un caracter absolut. De aceea o clasificare sau o anumită
ierarhizare a limbajelor de programare utilizate în momentul de față nu numai că este dificilă,
dar nu ar avea nici un beneficiu deoarece foarte des apar limbaje noi și diverse.
O altă clasă importantă de limbaje, sunt limbajele de asamblare, sau de nivel inferior,
ale căror caracteristici depind de sistemul de calcul considerat. În general, fiecare sistem de
calcul (sau tip de sistem de calcul), are propriul său limbaj de asamblare; de exemplu,
limbajul procesoarelor I NTEL se numește ASEMBLER. Instrucțiunile unui limbaj de
asamblare corespund cu operațiile simple ale sistemului de calcul iar stocarea datelor în
memorie este realizată direct de utilizator la nivelul locațiilor de memorie. Există de
asemenea anumite pseud o-instrucțiuni sau directive referitoare la alocarea memoriei,
generarea datelor, segmentarea programelor, și altele, precum și macroinstrucțiuni care
permit generarea unor secvențe tipice de program sau accesul la bibliotecile de subprograme.
În afară de limbajele evoluate și de limbajele de asamblare, există numeroase limbaje
specializate, numite uneori și de comandă, care se referă la o anumită clasă de aplicații.
Menționăm de exemplu limbajul pentru sisteme expert JESS, limbajele utilizate în cadrul
software -ului ma tematic Maple, și multe altele.
În general însă astfel de limbaje nu sunt considerate limbaje de programare propriu –
zise. Un program redactat într -un limbaj de programare poartă denumirea de program sursă.
Fiecare sistem de calcul, în funcție de particularitățile sale, are un anumit limbaj
propriu, numit cod mașină, acesta fiind singurul limbaj înțeles de procesorul sistemului. Un
astfel de limbaj depinde de structura procesorului, de setul de instrucțiuni, de posibilitățile de
adresare, etc. U n program redactat în limbajul cod mașină al sistemului de calcul îl numim
program obiect. Procesul de transformare al unui program sursă în program obiect se numește
compilare sau translatare. De obicei termenul de compilare este utilizat numai în cazul
limbajelor evoluate,în cazul limbajelor de asamblare fiind utilizat termenul de asamblare.

5
Compilarea (respectiv asamblarea) este efectuată de un program al sistemului numit
compilator (asamblor). De multe ori compilatoarele nu produc direct program obiect, ci un
text intermediar apropiat de programul obiect, care în urma unor prelucrări ulterioare devine
program obiect. De exemplu, compilatoarele sistemelor de operare DOS produc un fișier text
numit obiect (fișiere cu extensia obj) care în urma unui proces numit editare de legături și a
procesului de încărcare în memorie devine program obiect propriu -zis, numit program
executabil (fișiere cu extensia exe). Există posibilitatea cuplării mai multor module de
program realizate separat sau provenite din limbaje sursă diferite, rezultând în crearea unor
biblioteci de programe în formatul intermediar și utilizarea lor în alte programe.
Un program sursă poate fi executat de către sistemul de calcul direct, fără
transformarea lui prealabilă în program obiect. În aces t caz, programul sursă este prelucrat de
un program al sistemului numit interpretor. Acesta încarcă succesiv instrucțiunile
programului sursă, le analizează din punct de vedere sintactic și semantic apoi le execută sau
efectuează anumite operații auxiliare . O astfel de interpretare pură a unui program sursă este
totuși rar întâlnită.Cel mai adesea interpretoarele transformă mai întâi programul sursă într -un
format intern și crează anumite tabele cu informații, apoi textul intern este preluat de o
componentă pentru interpretare apoi executat. Faza de generare a textului intermediar este în
esență asemănătoare cu procesul de compilare iar formatul intern este asemănător, astfel
interpretarea și compilarea sunt comune.

6

II.1 Compilatorul

În ceea ce urmează voi prezenta unele principii și tehnici de compilare pentru limbaje de
nivel înalt, definite global sau parțial cu gramatici generative Chomsky de tipul doi sau trei;
limbajul de referință va fi limbajul JAVA.
Procesul de compilare este un proce s relativ complex și se bazează pe operații care au un
anumit caracter de autonomie. Din aceste motive procesul de compilare este de obicei
descompus în mai multe subprocese sau faze, fiecare fază putând fii considerată de sine
stătătoare. În principiu ace ste faze sunt parcurse secvențial (pot să existe și anumite excepții)
iar programul sursă este transformat succesiv în formate intermediare. Se poate considera că
fiecare fază primește de la faza precedentă un fișier cu programul prelucrat de faza
respecti vă.Se prelucrează fișierul respectiv și se furnizează un fișier de ieșire, iarăși într -un
format intermediar, acesta fiind utilizat în faza următoare. Există cinci faze de compilare
principale: analiza lexicală, analiza sistactica, generarea formatului int ermediar, generarea
codului, optimizarea codului și două faze auxiliare: tratarea erorilor și tratarea tabelelor.

Figura II.1 [1]

7

În continuare vom prezenta fiecare fază pe scurt insistând doar asupra analizei
lexicale.
Analiza lexicală are ca obiectiv principal determinarea unităților lexicale ale unui
program, furnizarea codurilor acestora și detectarea eventualelor erori lexicale. Pe lângă
aceste operații de bază, la analiza lexicală se mai pot efectua anumite operații auxiliare
precum: eliminarea bl ank-urilor (dacă limbajul permite utilizarea fără restricții a acestora),
ignorarea comentariilor, diferite conversiuni ale unor date (care se pot efectua la această
fază), completarea tabelelor compilatorului. Este posibil ca analiza lexicală să se realiz eze
global, pentru întregul program, caz în care analizorul lexical furnizează un fișier de ieșire cu
programul în format unitar și cu tabelele de informații necesare. Cel mai adesea însă
analizorul lexical tratează o anumită secvență de program sau lucrea ză chiar ca un
subprogram.În acest ultim caz, analizorul lexical este o rutină a analizorului sintactic care
este apelată succesiv pentru a furniza câte o unitate lexicală.
Analiza sintactică determină unitățile de text pentru care se pot genera formatul
intermediar și efectuează analiza lexicală a programului.Aceasta este faza principală a unui
compilator,deseori celelalte fiind apelate de aceasta pentru a se putea efectua părți din faza
aceasta.Tot ai ci se definitivează tabelele de informații și se realizează prelucrarea er orilor.
Generarea formatului intermediar transformă programul într -o formă numite
intermediară de la care se obține relativ ușor programul obiect.Această fază este strâns legată
de proiect ant în sensul formatului intermediar ales de proiectant și a metode i de implementare
aleasă de el.
Generarea codului este faza care generează codul obiect.În această fază se obține
programul în limbaj de asamblare obținut din codul sursă scris în lim baj evoluat.În mod
normal această fază se bazează pe rutine genera toare de cod co respunzător diverselor unități.
Optimizarea codului presupune îmbunătățirea codului obiect pentru a se obține un
program cât mai eficient din punct de vedere al memoriei și tim pului de prelucrare.Cel mai
des se elimină memoria redundantă și se optimizează ciclurile.
Tratarea erorilor și tratarea tabelelor influențează performanța din punct de vedere al
timpului de execuție și se elimină niște erori sintactice din program. [1]

8

II.2 Limbajul JAVA

Java este un limbaj de programare concurent orientat obiect pe bază de clase dezvoltat
special pentru a avea cât mai puține dependențe de implementare posibil.Are intenția de a
permite programatorilor să scrie o data și să ruleze oriunde (awrite once,run
anywhere”;WORA), adică codul care rulează pe o platformă nu trebuie recompilat pentru a
rula pe altă platformă

.
Figura II.1
Aplicațiile java sunt compilate în așa fel încât pot rula pe orice Java Virtual Machine
(JVM) indiferent de arhitectura sistemului de calcul.Începând din 2012 java este cel mai
popular limbaj de programare,mai ales în rândul aplicațiilor de web client -server, având peste
10 milioane de utilizatori.Limbajul este derivat din limbaje de nivel inferior C și C++ dar are
mai puține facilități de nivel inferior decât acestea.Compilatoarele Java,mașinile virtuale Java
și bibliotecile de clase implementate original și luate ca sisteme de referințe pentru alte
implementări și modificări au fost dezvoltate în 1991 de că tre Sun și au fost lansate pentru
prima dată în 1995.
Părinții fondatori James Gosling, Mike Sheridan și Patrick Naughton au inițiat în
iunie 1991 proiectul limbajul de programare Java.A fost dezvoltat inițial pentru televiziunea
prin cablu dar a fost prea avansat la vremea aceea pentru acea industrie.Denumirea inițială a
fost“Oak” (stejar ) dată după stejarul din fața biroului lui Gosling apoi a fost redenumit în
“Green” mai apoi in “Java” după denumirea cafelei pe care se presupunea că beau în cantități
mari creatorii limbajului.Gosling dorea să implementeze o mașină virtuală și un limbaj care
respectă un stil deja familiar de C/C++. [3]

9

Existau 5 caracteristici principale î n crearea limbajului Java:
1. simplu,orientat obiect și familiar
2. robust și sigur
3. neutru din punct de vedere al arhitecturii și portabil
4. performan țe mari
5. interpretabil, pe threaduri și dinamic
Versiunile java majore si datele lans ărilor:
 JDK 1.0 (Ianuare 21, 1996)
 JDK 1.1 (Februarie 19, 1997)
 J2SE 1.2 (Decembrie 8, 1998)
 J2SE 1.3 (Mai 8 , 2000)
 J2SE 1.4 (Februarie 6, 2002)
 J2SE 5.0 (Septembrie 30, 2004)
 Java SE 6 (Decembrie 11, 2006)
 Java SE 7 (Iulie 28, 2011)
O caracteristică a platformei Java este portabilitatea ceea ce înseamnă că programele
scrise în limbajul java trebuie să ruleze în mod similar indiferent de sistemul de operare sau
configurația hardware a sistemului de calcul pe care rulează.Această caracteristică este
menținută prin compilarea codului sursă java într -o reprezentare intermediară numită Java
Bytecode.Reprezentarea res pectivă este analoagă reprezentării cod mașină dar este parsata
către mașina virtuală java care aceasta este specifică sistemului de calcul pe care este menit să
ruleze.
Java nu aparține nici unui standard ANSI sau ISO deci aparține unui standard “de
facto ” însemnând că a devenit în sine un limbaj standard dominând piața din cauza liberii
alegeri a utilizatorilor.Implementarea oficială este împărțită în 2 distribuții:
 Java Runtime Enviroment (JRE) ce con ține componentele necesare pentru a rula
programe Java si este menit utilizatorilor aplica țiilor.
 Java Development Kit (JDK) ce con ține componentele necesare dezvolt ării programelor
si este menit programatorilor de Java.
Sintaxa Java este în principal derivată din C++, dar spre deosebire de aceasta,
limbajul Java a fost construit aproape exclusiv ca fiind orientat obiect.Totul se scrie într -un
fișier clasă și este văzut ca fiind obiect cu excepția tipurilor de date primitive care nu sunt
văzute ca clase pentru a facilita performanța programului.Spre deosebire de C++, Java nu
suportă supraîncărcarea operatorilor sau moșteniri multiple pentru clase.Acest lucru
simplifică limbajul și ajută în prevenirea unor potențiale erori și a design -ului anti -model

10
(anti-pattern). Java folose ște metodele de coment arii asem ănătoare lui C++.Sunt 3 stiluri
diferite de com entarii:[3]

– coment ariu pe o singur ă linie marcat cu / /,coment ariu pe mai multe linii care se
marcheaz ă cu deschiderea /* și se închide cu */ , și stilul de comentare javadoc

care se deschide cu /** și se închide cu */.Stilul Javadoc de comentare permite utilizatorilor
să ruleze executabilul Javadoc pentru a compila documentație pentru program.Exemple:

Exemplul “Hello world”:

La deschiderea unui program se genereaz ă tradiționalul program Hello Java.Acesta se poate
scrie astfel:
class HelloWorldApp{
public static void main(String[] args){
System.out.println(“Hello World!”);
}
}
Pentru a compara acest limbaj de programare cu altele s ă analiz ăm acest exemplu.
Fișierele sursă trebuie să fie numite după clasa publică pe care o conțin urmate de sufixul
.java,de exemplu, HelloWorldApp.java. Aceasta este pentru început compilat în formatul
bytecode folosind un compilator Java și se produce un fișier numit HelloWorld App.class.
Doar după acest pas se poate executa sau lansa. Fișierul sursă java poate să conțină doar o

11
clasă publică, dar poate să conține oricâte clase care au alt acces și oricâte clase interioare
publice.
O clasă care nu este publică poate fi stocată în orice fișier .java. Compilatorul va genera un
fișier clasă pentru orice clasă definită în codul sursă. Numele fișierului clasă este dat de
numele clasei urmat de extensia “.class”. Pentru generarea fișierelor de clasă, clasele anonime
sunt tratate ca și c um numele lor ar fi dat de concatenarea numelui clasei în care sunt
înscrise,caracterul $ și a unui număr întreg [3].

Cuvântul cheie public arată că o funcție poate fi apelată și în alte clase sau că o clasă poate fi
folosită de alte clase care nu corespund aceleiași ierarhii. Ierarhia claselor este legată de
numele directorului în care fișierul .java este localizat.
Cuvântul cheie static în fața unei metode indică o funcție statică care este asociată numai
clasei și nu cu orice instanță specifică a clasei. Doar metodele statice pot fi invocate sau
apelate fără a se referi la un obiect. Metodele (funcțiile) statice nu pot accesa vreun membru
nestatic al unei clase.
Cuvântul cheie void indică faptul că funcția main nu returnează nici o valoare către a pelant.
Dacă un program java se termină cu un cod de eroare, acesta trebuie să apeleze
funcția System.exit() în mod explicit.
Cuvântul main nu reprezintă un cuvânt cheie în limbajul Java, este pur și simplu funcția pe
care lansatorul java o apelează pentru a îi da controlul programului scris, adică pentru a îi
începe rularea.Clasele Java care rulează în medii specifice precum applet -uri sau Enterprize
JavaBean nu necesită funcția main. Un program Java poate să conțină mai multe clase care
conțin funcția main iar în acest caz mașinii virtuale îi trebuie ilustrat explicit de la care clasă
să înceapă rularea.
Funcția main trebuie să accepte o mulțime (un array) de obiecte de tip String (mulțime de
caractere). Prin convenție, este numit args deși se poate folosit orice identificator.Începând cu
Java 5,funcția main poate folosi și argumente variabile care permit invocarea metodei cu un
număr arbitrar de argumente string .De exemplu:
public static void main(String… args)
Efectul acestei declarații este identic din punct de vedere semantic cu declarația normală,
adică se acceptă tot o mulțime de obiecte de tip array, dar permite o sintaxă alternativă pentru
crearea și p arsarea mulțimii de tip string.
Lansatorul java lansează Java prin încărcarea în memorie a unei cla se specificată în linia de
comandă sau dată ca și atribut într -un fișier JAR și apelarea metodei public static void
main(String[]). Programele stand -alone (aplicații de sine stătătoare) trebuie să prezinte în
mod explicit funcția aceasta. Parametrul String [] args este o mulțime de obiecte de tip string

12
care conține orice argumente parsate clasei. Parametrele pentru main sunt de obicei par sade
folosing linia de comandă.
Afișarea face parte din librăriile standard Java. Clasa System definește un câmp public s tatic
numit out.Obiectul out este o instanță a clasei a €œPrintStream”și prezintă multe metode de
afișarea a datelor către ieșirea standard, inclusiv “println(String)” care mai adaugă la finalul
Stringului și caracterul de linie nouă .
Stringul “Hello,world! ” este convertit la un obiect de tip String de c ătre compilator [3].

Java este un limbaj foarte folosit la ora actuală. Un exemplu bun este dat de Google și
Android Inc. care au ales să folosească Java ca și sistemul de bază pentru crearea sistemului
de operare Androi d. Deși sistemul de operare a telefoanelor este construit pe baza kernelului
linux care este scris în C, Androidul folosește Java pentru aplicațiile dezvoltate.Gaikai
folosește plugin -ul de Java browser pentru a face streaming de demouri de j ocuri pentru PC.
Gaikai înseamnă în japoneză “ocean deschis” și este un serviciu pe bază de cloud computing
care prin intermediul internetului transmite date către utilizatori.La ora actuală a apărut doar
un competitor în acest domeniu “On-live” [21].

Figura II.2[3]

13

Figura II.3[21]
Bibliotecile de clase Java se compun din bytecodurile compilate a codurilor sursă create de
implementarea JRE pentru a facilita dezvoltarea aplicațiilor Java . Niște exemple:
Bibliotecile principale (core libraries) conț in:
 biblioteci de colectie care implementeaza structurile de date precum dictionare,liste
etc.
 biblioteci de procesare a fisierelor XMLpentru parsare,transforrmare,validare etc.
 biblioteci pentru securitate
 biblioteci de internationalizare si localizare
Bibliotecile de integrare permit creatorilor de aplicații să comunice cu sisteme externe :

14
 Java Database Connectivity (JDBC) pentru accesarea bazelor de date
 Java Naming and Direc tory Interface (JNDI) pentru cautare si descoperirea obiectelor
dupa nume
 RMI si CORBA pentru crearea aplicatiilor distribuite
 JMX pentru evidentierea si monitorizarea aplicatiilor (pentru management) [3]

Biblioteci pentru interfa ța utilizator care inclu d:
 Abstract Window Kit (AWT) care include componente pentru grafica utilizator (GUI)
si mijloacele necesare pentru manipularea lor
 SWING care este construit in AWT dar contine
implementari a widgeturilor AWT
 biblioteci pentru tratarea semnalelor audio
Din punct de vedere al documentației Javadoc este un
sistem de documentație care este foarte vast și folosit de
mulți creatori de aplicații Java. Acest sistem este creat
de Sun Microsystems și le oferă programatorilor un
sistem bine organizat pentru documentar ea aplicațiilor
lor.
Corporatia Sun a creat 4 distribuții a sistemului Java,
fiecare specializată pe un anumit mediu de rulare a aplica țiilor: . Figura II.4 [3]
Vezi figura II.4.
Java Card – smartcarduri
Java Platform, Micro Edition – medii cu resurse limitate
Java Plat form, Standard Edition – stații de lucru obiș nuite
Java Platform, Enterprise Edition (Java EE) – mediul de internet si enterprise .

II.3 Noțiunea generală de limbaj

Noțiunea de limbaj poate fi definită pe multe domenii precum mat ematică, logică,
informatică, lingvistică.Noi vom trata un limbaj cu definiții generale și operații din punct de
vedere al informaticii și vom introduce atât concepte generale cât și axate pe studiul nostru.
Un alfabet este o mulțime finită și nevidă iar e lementele le vom numi litere sau
simboluri.Un cuvânt peste alfabet este un șir de litere din alfabet.Un limbaj peste alfabet este

15
o mulțime de cuvinte peste alfabet.Pentru a înțelege mai ușor conceptul nostru de cuvânt și
alfabet vom ilustra niște exemple ușoare de înțeles.Un exemplu de alfabet este mulțimea de
caractere {Q,W,E} iar un cuvânt peste acest alfabet (care se poate genera) este de exemplu
QWEWQEW.De aici se înțelege că un alfabet conține niște caractere iar un cuvânt este o
înșiruire a caractere lor.O observație este că în funcție de proprietățile limbajului acesta s -ar
putea să accepte și elementul vid, adică cuvântul care nu are nici un caracter.
Limbajele sunt mulțimi de cuvinte, deci asupra lor se pot aplica operații cu mulțimi
sau operații sp ecific teoriei limbajelor formale. Astfel se pot construi alte. Operațiile uzuale
definite sunt binare: concatenare, intersecție, reuniune, diferență, câtul la dreapta și unare:
complementul limbajului, închiderea Klein și inversul unui limbaj. Nu vom apro funda
operațiile deoarece nu sunt necesare pentru cazul nostru. Vom studia doar limbajul Java, nu și
crearea lui sau compunerea cu alte limbaje.
Dacă limbajul nostru este o mulțime finită atunci el poate fi descris ilustrând efectiv
cuvintele.Dacă este o m ulțime infinta atunci poate fi descris punând în evidență structura
cuvintelor .
Un limb aj poate fi specificat formal în mai multe moduri:
 siruri produse de o anumita gramatica
 siruri notate prin expresii regulate
 siruri acceptate de un automate finite
Există două procedee generale pentru definirea unui limbaj: generativ prin generarea
tuturor cuvintelor limbajului și analitic bazat pe determinarea apartenenței unui cuvânt la
limbaj [2].

16

Capitolul III Limbaje regulate si automate finite

Automat ele finite sunt mecanisme pentru recunoașterea limbajelor finite. Un automat finit are
2 componente importante:banda de intrare și dispozitivul de comandă .Pe banda de intrate
sunt înregistrate simbolurile alfabetului de intrare și se generează cuvinte.Dispozitivul de
comandă se află în permanență într -o anumită stare care aparține schemei de stări .
Automatul finit funcționează în pași discreți .Un pas presupune citirea unui caracter
de pe banda de intrare și schimbarea stării dispozitivului d e comandă în mod corespunzător.
Automatul se oprește când se ajunge la finalul bandei de intrare, astfel obținându -se o stare
finală .
Din punct de vedere matematic un automat finit este un sistem
unde:

Un automat finit se poate bloca doar dacă în starea actuală se citește un caracter de pe banda
de intrare și folosind acest caracter și starea noastră rezultatul este vid.
Dacă bazându -se pe starea actuală și pe caracterul obținut din banda de intrare,
dispozitivul de comandă poate rezulta 0 sau 1 stare atu nci automatul se numește determinist,
altfel se numește nedeterminist.
Pentru a înțelege cât mai ușor aceste două concepte vom explica nedeterministul
printr -un exemplu simplu. Suntem în starea A. Dacă cu caracterul W se poate ajunge în două
stări B și C f ără restricții atunci automatul este nedeterminist (AFN). Dacă se poate ajunge
într-o singură stare doar, atunci automatul este determinist (AFD) .

Figura III.1 [2] Figura III.2 [2]

17
III.1 Limbaje regulate și expresii regulate

Expresiile regulate sunt cuvinte peste un vocabular împreună cu op eratori i|(sau) ·(produs) și
*(închidere ).
Construirea unei reguli se face astfel:
(1) xsi∅sunt expresii regulate;
(2) pentru orice a∈V , cuvântul a este o expresie regulată ;
(3) daca R si S sunt expresii regulate, atunci ( R|S) (R · S ) si (R*) sunt expresii regulate;
(4) orice expresie regulată se obține prin aplicarea de un număr finit de ori a regulilor (1) -(3).

În domeniul științific, o expresie regulată (abreviat regex sau regexp) este o secvență de
caractere de text, dintre care unele sunt considerate metacaractere cu sens simbolic, altele au
sensul lor literal. Aceste concept a apărut în anii 1950 când Kleene a formalizat descrierea
unui limbaj regulat și s -a obișnuit cu programele date de Unix pentru procesarea de text.
Pentru a înțelege acest concept vom da un exemplu. O întrebuințare foarte simplă a
expresiilor regulate este în editoare text pentru a afla dacă același cuvânt este scris în mai
multe moduri.De exemplu ambele cuvinte seri alize și serialise sunt corecte și pentru a nu
scrie două verificări se va expune expresia seriali[s|z]e.
Un procesor de expresii regulate procesează o expresie regulată ca fiind o gramatică expusă
în limbaj formal.O dată cu varietatea limbajelor a apărut și o varietate de sintaxe și gramatici,
astfel apărând diferite sisteme de expresii regulate. Procesorul de expresii compilează codul
primit (expresiile) și folosind rezultatul analizează textul țintă, parsândul pentru a analiza
substringuri (părți din te xtul țintă) astfel aflând care sunt membre a limbajului.
Expresiile regulate sunt foarte folositoare în domeniul informaticii încât utilizatorii frecvenți
susțin că ar trebui se devină un standard pentru toți. La ora actuală sistemele de expresii
regulate au evoluat la punctul de două standarde pentru gramatici și sintaxă, unul simplist
“basic” si unul mai complex “extended”. Exist ă expresii regulate “moderne” care dezvoltă
drastic domeniul, care sunt asemenatoare pe mai multe platforme și aplicații. Expre siile
regulate sunt folosite și nativ în unele limbaje de programare. Unele limbaje au un sistem
direct implementat iar altele au nevoie de biblioteci suplimentare. Perl și Ruby au expresiile
regulate implementate direct în limbaj iar Java, C++ și Python n ecesită biblioteci
specializate [1].
Originea expresiilor regulate se află în teoria automatelor și teoria limbajelor formale, mai
exact în pattern matching(potrivirea modelelor), prin studierea modelelor computaționale
(automate) și căutarea metodelor de descriere și clasificare a limbajelor ilustrate formal. În
anul 1950 matematicianul Stephen Cole Kleene a descris modelele folosind notația sa
matematică numită “seturi regulate”. Prima implementare a pattern matching -ului a fost
limbajul SNOBOL care se baza pe structuri asemănătoare cu expres iile regulate. Expresiile
regulate în sensul lor au apărut prima dată în formatul unui program când Ken Thompson a
construit notațiile lui Kleene folosindu -le ca un mijloc de potrivire a modelelor în fișiere text .

18
Expresiile regulate specifică seturi de ca ractere. Se preferă definirea unor reguli decât unor
liste de caractere.Unei expresii regulate îi putem asocia un anumit limbaj peste V iar în cazul
acesta spune că expresia regulată desemnează acel limbaj. Pentru a înțelege mai ușor vom
ilustra un exemplu mic:
Pentru a recunoaște următoarele cuvinte “qr” “qwr” “qer” este necesară următoarea
expresie: q(w|e?)r
Sunt furnizate diverse operații și notații necesare pentru a construi o expresie regulată.Vom
ilustra câteva:
| sau
() grupare – pune in evidenta ordi nea de aplicare a operatorilor
? – nici una sau doar o secventa
* inchidere – de la nici unul la repetitii infinite a secventei respective
[a-b] caractere aflate in raza respectiva [1]

III.2 Sisteme tranziționale

Un sistem tranzițional este un sistem de forma
unde:

Exemplu: ∑={𝑠0,𝑠1,𝑠2} , I={0,1}, ∑={𝑠0,𝑠1} 0 ,∑={𝑠2} 𝑓 iar funcția și relația de tranziție
este următoarea :
f 𝑠0 𝑠1 𝑠2
0 {𝑠1} {𝑠2} {𝑠0}
1 ∅ {𝑠0,𝑠1} {𝑠0,𝑠2}
𝛿={(𝑠0,𝑠1),(𝑠2,𝑠1)}
Se poate construi acum diagrama de stări completă :

19

Figura: III.3[1]
Un sistem tranzițional explicat cel mai simplu este prin prezentarea tabelului de
tranziție. În funcție de starea actuală și caracterul introdus vom obține o nouă stare. Astfel se
parcurge tabelul până se ajunge la o stare finală.
Fiind dată o expresie regulată putem întotdeauna construi un sistem tranzițional care
recunoaște cuvântul reprezentat de expresia respectivă.Această construcție se face în mod
recurent folosind diagrama de stări.O consecință a folosirii sistemului tranzițional este că
limbajul studiat și implicit și expresii vor fi obligatoriu regulate.
Un exemplu pentru expresia q(w|e?)r este dat de sistemul:

Figura III.4[1]

20
III.3Analiz a lexicală

Procesul de analiză lexicală este o fază a procesului de compilare în care se determină
unitățile lexicale (cuvinte, atomi) ale unui program sursă, se furnizează codurile interne ale
acestora și se detectează eventualele erori lexicale. Analizorul lexical mai poate efectua o
serie de operații auxiliare precum: eliminarea blank -urilor, ignorarea comentariilor, diferite
conversiuni ale unor date, completarea tabelelor compilatorului, gestiunea liniilor textului
sursă.
O unitate lexicală (Lexic = vocabular) este o secvență de caractere din textul sursă
care are o anumită val oare logică.Definiția riguroasă a unităților lexicale ale unu limbaj de
programare particular se dau la definirea efectivă a limbajului de programare.În mod uzual
unitățile lexicale alese sunt: cuvinte cheie, identificatori, constante, opera tor și delimita tori.
Unitățile lexicale se pot împarți în două categorii : simple si compuse (atributive).
Orice limbaj rezonabil poate fi folosit pentru implementarea unui analizor
lexical.Unitățile lexicale se pot specifica cu ajutorul limbajelor regulate, deci folosind
gramatici de tipul 3 sau expresii regulate. Ambele specificații conduc la construirea de
automate finite echivalente care sunt ușor programabile.
Pentru a înțelege ce este un analizor lexical va trebui să punem bazele a ceea ce este
un compilator,cod surs ă,aplicație finală și limbaj de programare.Acești termeni sunt fixați
anterior iar pe baza acestora vom continua să dezvoltăm asupra subiectului și vom lua acolo
unde este necesar niște exemple foarte simpliste.
Unitățile pot fi împărțite în două categorii din punct de vedere al analizei lexicale și al
modului de prelucrare:
1) Unități lexicale simple care nu conțin atribute suplimentare, de exemplu: cuvinte
cheie și operatori.
2) Unități lexicale compuse care conțin atribute suplimentare, de exemplu
identi ficatori și constante.Atributele sunt informații specifice precum tipul identificatorului
sau al constantei (intreag, real, etc.). Este obligatorie specificarea tipului unei date încă din
începutul programului deoarece structura programului obiect sau repr ezentare a internă
depinde de acest tip.
Reprezentarea internă a unităților lexicale se face în funcție de categoria lor.Cele
simple sunt reprezentate printr -un cod specific (de exemplu număr întreg). Unitățile lexicale
compuse se reprezintă prin cod și inf ormația (de natură semantică) corespunzătoare. În acest
caz unitatea lexicală se reprezintă intern printr -un cod urmat de o referință într -un table[2] .

Informația conținută de tabel ar putea fi pentru constante: cod, tip, valoare, iar pentru
identificato ri: cod, tip, indicator de inițializare.

21
De obicei compilatoarele utilizează tabele pentru stocarea atributelor (tabel de
constante, tabel de variabile, tabel de etichete, etc.).
Este posibil ca o clasă de unități lexicale simple să se reprezinte printr -un cod unic și
un atribut pentru distingerea lor în cadrul clasei. Lista unităților lexicale și definiția riguroasă
a acestora se da la proiectarea compilatorului.
Analizorul primește textul sursă și produce unitățile lexicale în codificare internă.
Pentru o înțelegere mai ușoară vom lua un exemplu simplu și vom arăta unitățile recunoscute
în codificare internă,dar le vom expune într -o manieră ușor de înțeles.
{
if(a>10)
a=a/10;
return a;
}
Unele unități lexicale se repeta în cod dar în tabel le vom scrie doar o dată .

Cod Unitate lexicala Atribut
{ DESCHIDERE
ACOLADE
if CUVANT CHEIE if
( DESCHIDERE
PARANTEZE
a IDENTIFICATOR referinta
> OPERATOR
10 CONSTANTA referinta
) INCHIDERE
PARANTEZE
= OPERATOR
/ OPERATOR
return CUVANT CHEIE return
; OPERATOR
} INCHIDERE ACOLADE

Tabelul asociat unitatilor lexicale [xy][2].
Codul nostru va produce deci urmatorul sir de unitati lexicale:
[DESCHIDERE ACOLADA]
[CUVANT CHEIE,if][DESCHIDERE PARANTEZE][IDENTIFICATOR,a][OPERATOR]
[CONSTANTA,10][INCHIDERE PARANTEZE]
[IDENTIFICATOR,a][OPERATOR]
[IDENTIFICATOR,a][OPERATOR][CONSTANTA,10][OPERATOR] [CUVANT
CHEIE,return][IDENTIFICATOR,a][OPERATOR]
[INCHIDERE ACOLADE]

22

În lista reprezentărilor interne de mai sus, identificatorii, constantele și cuvintele cheie
au atribute suplimentare care sunt de fapt niște adrese relative sau referințe în tabel.
Majoritate limbajelor de programare conțin și secvențe de text care nu sunt
considerate unități lexicale,dar au acțiuni specifice, de exemplu comentariile și directivele de
preprocesare.Trebuie menționat că înaintea analizei lexicale prepriu -zisă, se preproceseazaă
textul unde se tratează de obicei comentariile, directivele de preprocesare și secvențe care
depinde strict de limbaj și compilator.Specificarea unităților lex icale, adică definirea
riguroasă se face de către proiectantul limbajului. O posibilitate de descriere este limbajul
natural:
“Un identificator este o secvenț ă nelimitată de litere Java și cifre Java,dar prima
trebuie să fie o literă Java.O literă Java conține caraterele ASCII pentru litere mari și litere
mici precum și caracterele _ (liniuța jos) și $ (semnul dolar) din motive istorice. Cifrele Java
includ cara cterele ASCII de la 0 pana la 9”
Un analizor lexical poate fi implementat în orice limbaj rezonabil.Analizorul nostru se
bazează pe expresii regulate luate de pe site -ul oficial al limbajului Java, astfel realizarea
efectivă se va rezuma la simularea funcț ionării unui automat finit.
Varianta de programare aleasă atașează o secvență de program la fiecare stare a
automatului. Dacă starea nu este stare finală atunci secvența citește următorul caracter din
textul sursă și găsește următorul arc din diagrama de s tări. Depinzând de rezultatul căutării se
transferă controlul altei stări sau se returnează eșec (posibilă eroare lexicală).Dacă starea este
finală atunci se apelează secvența de returnare a codului unității lexicale și instalare unității
lexicale în tabel elul compilatorului.
Pentru simplificarea implementării se caută următoarea unitate lexicală prin
încercarea succesivă a diagramelor corespunzătoare fiecărei unități lexicale într -o ordine
prestabilită. Eroarea lexicală se semnalează doar atunci când toate încercările se încheie cu
eșec.De obicei textul sursă conține și secvențe ce se pot descrie tot cu ajutorul expresiilor
regulate, dar care nu sunt unități lexicale (de exemplu comentariile). Aceste sec vențe nu vor
genera cod lexical [2].
Pentru a evita ap ariția unor caractere necunoscute în textul sursă se consideră și
limbajul ce constă din toate simbolurile ASCII. Astfel, indiferent de unde începe analiza
textului, programul de analiză lexicală găsește o potrivire cu o descriere, specificația fiind
compl etă.
Există posibilitatea ca mai multe secvențe cu aceeași origine să corespundă la diferite
descrieri ale unităților lexicale sau să fie comune p ână la un anumit punct. Se consideră
unitate lexicală cel mai lung șir ce se potrivește unei descrieri (longes t match rule). Dacă sunt
două reguli care se potrivesc la același șir de lungime maximă atunci se consideră o prioritate
asupra descrierilor (rule priority).

23
De exemplu, în cazul următor ,i if if8
unita țile lexicale delimitate vor f iiidentificator, if cuvânt cheie, if8identificator.
Regulă de prioritate se aplică pentru potrivirea lui if cu identificator și cuvânt cheie,
cuvânt cheie fiind mai prioritar. Pentru depistarea celei mai lungi potriviri, din punct de
vedere al programării analizorului, vom fi foart e atenți la alegerea separatorilor unităților
lexicale pentru a fi siguri că se ajunge la stare finală doar în punctul dorit .
Cea mai costisitoare operațiun e (ca timp de procesare) din analiza lexicală este
ignorarea comentariil or. Primele generatoare auto mate de analizoare lexicale și sintactice au
apărut în anii ’70 și au fost incluse în sistemul de operare Unix.
Etapele realizării unui analizor lexical:
 ETAPA1: Descrierea unităților lexicale cu ajutorul expresiilor regulate
Definițiile riguroase a unităț ilor lexicale sunt luate de pe sursă oficială și manual se vor
construi expresii regulate pentru fiecare caz întâlnit.
 ETAPA2: Corespunzător expresiilor obținem automatele finite deterministe și
construit sistemul tranzițional
 ETAPA3: Ultima etapă presupun e programare efectivă a analizatorului
Automatul finit obținut are stările finale asociate cu clasele de cuvinte recunoscute . Se
asociază acțiuni stărilor finale, corespunzător definițiilor unităților lexicale (de exemplu
pentru constante numerice se gener ează reprezentarea internă și se memorează în tabelul
compilatorului). [2]

III.4Analizorul lexical pentru limbajul Java
ETAPA 1
Conform celor menționate mai sus vom începe să definim unitățile lexicale folosind
expresii regulate .
Programele Java sunt scrise folosind setul de caractere Unicode, dar acestea sunt
convertite în caractere ASCII.Caracterele Unicode sunt cea mai mare convenție de notație a
literelor și cifrelor la nivel global. Deoarece sunt multe limbi existente, fiecare cu setul lor de
caractere acest Unicode le poate reprezenta pe toate indiferent de program,platformă sau
limbă.Caracterele ASCII (AMERICAN STANDARD CODE for INFORMATION
INTERCHANGE) reprezintă de fapt primele 128 de caractere Unicode UTF -16.Acestea sunt
suficiente pentru a an aliza un cod sursă Java cu excepția unor mici ocazii .
Codul sursă al programului nostru se împarte pe rânduri și apoi este analizat rând cu
rând.Se poate face acest pas din cauza prezenței caracterului ASCII “terminator de sir”.Acest
caracter putem spune ca este mai special. În funcție de sistemul de operare avem situații în

24
care dăm doar de caracterul ‘\n’ (newline) sau ‘ \r’ (linereturn), sau chiar de ambele caractere
una dupa alta (‘ \r’‘\n’) care sunt luate ca fiind doar un terminator de linie și nu
două .Terminator de sir va avea deci urmatoarea expresie terminator={‘ \n’| ‘\r’| ‘\r \n’} .
În acest punct vom întâlni în codul de analizat următoarele caractere:
I. spații albe
II. comentarii
III. tokenuri care se împart în următoarele :
1. identificator
2. cuvant cheie
3. literal
4. separator
5. operator
Spațiile albe și comentariile sunt ignorate de analizorul lexical, dar noi le vom defini pentru a
le putea recunoaște.Tot ceea ce nu este spațiu alb sau comentariu este un token [19].
Un to ken este un simbol terminal al gramaticii sintactice în java.Spațiile albe și comentariile
mai servesc ca și separatori pentru token -uri care dacă sunt adiacente se analizează diferit și
se iau ca fiind unul singur.Un exemplu este “x – = 3” rezultă în {ide ntificator, operator,
operator,literal} iar “x -= 3” rezultă în {identificator,operator,literal}. [7]

I.Spatiile albe sunt caracterele ASCII care reprezinta spatiu, tab orizontal, caracterul
formfeed si terminatoarele de linie:
‘ ’ – spatiu
\t – tab orizontal
\f – formfeed
\n , \r , \r\n – terminatorii de linie
Expresia regula este ‘ ’| \t|\f|\n|\r dar luand in calcul si impartirea pe randuri anterioara este
suficient doar expresia ‘ ’| \t|\f .
II. Comentariile sunt de doua tipuri,iar din punct de veder e al prioritatii se aplica regula de
primul venit primul servit:
/*…*/ comentariu traditional
// comentariu de linie
Expresia regulata pentru comentarii devine /* (orice caracter)* */ | // (orice caracter in
afara de terminator de linie)* ( \n|\r)
III.Tokenurile se impart in mai multe categorii.Primul este identificator dar pentru a intelege
mai usor acest concept de identificator vom incepe cu cuvinte cheie si cu doi literali [5].

25
2.Limbajul Java are 50 de cuvinte cheie.Un cuvant cheie este o secven ta de caractere
care nu poate fi folosit ca si identificator.Acestea sunt:
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while

Expresia regula a cuvintelor cheie este de forma abstract|continue|…|while .
Cuvintele “const” si “goto” sunt considerate cuvinte cheie deși nu sunt folosite la ora
actuală.Cuvintele “true” si “false” par a fi cuvinte cheie dar defapt sunt literali booleeni.În
mod asemănător,cuvântul null nu este cuvânt cheie ci este literal nul.Ac ești literali îi vom
explica în detaliu mai jos [11].
Un identificator este o secvență nelimitate de litere Java și numere Java,dar obligatoriu
trebuie să înceapă cu o literă Java.Un identificator nu are voie să fie cuvânt cheie, literal
boolean sau literal nul [6 ].

Din cauza acestei definiții a trebuit să explicăm cuvintele cheie,literalii booleeni și literalul
nul.
Literele Java sunt caracterele [a -z] , [A -Z] si din motive istorice semnul _
(underscore) si $ (semnul dolar). Cifrele Java sunt caract erele [0 -9]
Expresia regulata pentru identificator este: ([A -Z]|[a -z]|_|$)([A -Z]|[a -z]|_|$|[0 -9])*
3. Un literal este reprezentarea în cod sursă a unui tip de dată primitiv.Literalii se
împart în 6 categorii :
a. literal intreg
b. literal in v irgula flotant
c. literal boolean
d. literal caracter
e. literal sir de caractere (string)
f. literal nul [8].
a.Un literal intreg poate sa reprezinte un numar intreg in bazele 10,2,8,16.Toti literalii intregi
poate sa aiba la final litera “L” sau “l” (L mic), deci formulelor urmatoa re le vine atasat la
final (L|l)? :

26
In baza 10 numerele sunt de forma: 0|( [1 -9](_|[0 -9])*[0 -9])?
In baza 2 numerele sunt de forma: 0(b|B)[0 -1]((_|[0 -1])*[0 -1])?
In baza 8 numerele sunt de forma: 0[0 -7]((_|[0 -7])*[0 -7])?
In baza 16 numerele sunt de forma: 0(x|X)[0 -9,a-f,A-F]((_|[0 -9,a-f,A-F])*[0 -9,a-f,A-F])?[13].
b.Un literal in virgula flotanta se poate exprima in baza 10 sau in baza 16.Expresiile regulate
care le corespund sunt:
In baza 10: 0|( [1 -9](_|[0 -9])*[0 -9])? . ( [0 -9](_|[0 -9])*[0 -9])? e (+| -)?( [0-9](_|[0 -9])*[0 -9])?
(f|F|D|d)?
In baza 16: 0(x|X)[0 -9,a-f,A-F]((_|[0 -9,a-f,A-F])*[0 -9,a-f,A-F])? . [0 -9,a-f,A-F]((_|[0 -9,a-f,A-
F])*[0 -9,a-f,A-F])? e [0 -9,a-f,A-F]((_|[0 -9,a-f,A-F])*[0 -9,a-f,A-F])? (p|P)? [14].
c.Literalul boolean are doar 2 valori posibil e “true” sau “false”.Expresia regulata va fi
true|false [15].
d.Un literal caracter este ilustrat printr -un caracter sau o secventa unicode de iesire
incapsulata in simbolul apostrof ‘ .Expresia regulata este:
’ (caracter) | \((b|t|n|f|r|”|’| \)?|[0-7|([0-7][0-7])|([0 -3][0-7][0-7])][16].
e.Un literal string accepta orice input chiar si vid.Se deschide si se inchide cu ”.Sa fim atenti
doar ca un literal string se poate intinde pe un rand doar. Ex presia regulata este “(orice)” [17].
f.Literalul nul are o valo are doar care este referint nula ilustrata prin cuvantul null. Expresia
regulata este: null [18].
4.Exist ă 9 separatori :
{ } [ ] ( ) ; , .
Expresia regulata este: {|…|. [9].
5.Operatorii sunt urmatorii in numar de 37:
= >< ! ~ ? :
== <= >= != && || ++ –
+ – * / & | ^ % <<>>>>>
+= -= *= /= &= |= ^= %= <<= >>= >>>= [10].

27
Expresia regulată o vom scrie pe anumite categorii în funcție de caracterul cu care ne intră în
sistem vom întâlni niște situații :
= =?
<<? =?
>>? >? =?
! =?
& (&|=)?
| (‘|’|=)?
+ (+|=)?
– (-|=)?
* =?
/ =?
^ =?
% =?
la care mai adaug ăm |~|?|: [10]

ETAPA 2
Folosind ex presiile regulate obținute vom construi sistemul nostru tranzițional necesar pentru
recunoașterea cuvintelor.
Menționăm că anterior implementării efective a acestui pas programul nostru va
împărți textul sursă pe linii. Doar după acest pas analizorul nostru lexical va intra în acțiune.
Vom folosi o variabilă pentru a ține minte linia și coloana pe care ne aflăm în textul nostru
astfel având libertatea de deplasare înapoi acolo unde este caz ul.Pentru a putea crea tabelul
compilatorului este suficient să știm doar tipul unităților noastre lexicale.
Starea de î nceput este starea 0, stările finale sunt marcate cu cerc dublu încercuit .

28

[III.5][1]

Starea A reprezinta comentarii
Starea B reprezinta cuvinte cheie
Starea C reprezinta identificatori
Starea D reprezinta literali
Starea E reprezinta separatori
Starea F reprezinta operatori
Starea G reprezinta spatii albe
Alegerea stării spre care se deplasează automatul nost ru va depinde strict de primul
caracter. O primă observație este că automatul nostru se va bloca dacă se îndreaptă spre o
stare finală dar pe parcurs nu poate să treacă într -o altă stare. Pentru a r ezolva această
problemă vom crea o funcție care va obliga automatul să itereze toate drumurile pentru a

29
ajunge la stări finale. Când se ajunge la stare finală se va returna un rezultat și apoi se va
reseta sistemul la starea 0, fiind pregătit să analizeze următoarea unitate lexicală .
ETA PA 3
Această etapă este realizată în mod practic mai jos cu explicații de rigoare, decizii de
implementare și resurse folosite.
În situația cuvintelor cheie se citește cuvântul și se compară cu cel din memorie.Pentru a
simplifica acest proces se încarcă în memoria unui tabel de dispersie (hashtable) toate
cuvintele cheie și se compară cu acestea.
În situația separatorilor procesul de identificare a unității lexicale este simplu. Se compară
caracterul introdus cu toate separatoarele și se alege cel bun.
În situația operatorilor este necesar să introducem niște stări intermediare pentru a facilita
stările terminale cu o potențială continuare.
In cazul caracterului ‘>’ acesta este t erminal daca nu este urmat de încă un caracter ‘>’ astfel
obținându -se operatoru l ‘>>’ și nu doi operatori ‘>’.
Vom dezvoltă aceste situații mai jos în explicarea aplicației pentru că este mai ușor de înțeles
din implementarea practică.
Tabelul de dispersie este o clasă Java din pachetul util folosită pentru a mapa chei unor
valori. Orice obiect nenul poate fi folosit ca și cheie și ca și valoare. În implementarea aceasta
s-au ales cheile de tip string și va lorile de un tip definit de noi [1].

30
Capitolul IV Descrierea a plicati ei software
Prin software , soft sau rare ori și „l ogicial” se înțelege un system de programe
pentru calculatoare incluzând procedurile lor de aplicare, sistem f urnizat odată cu
calculatorul respectiv sau creat ulterior de către utilizator sau și cumpărat din comerț de -a
gata. Prin contrast, cuvântul hardware desemnează partea fizică a calculatorului sau a
sistemului informatic respectiv. În general, pentru a funcționa, un sistem informatic are
nevoie de ambele componente, în plus și de datele care trebuiesc prelucrate. Uneori și aceste
date sunt considerate a face parte din software.
Componenta software poate include toată gama de produse de programare, uzual formată
din sistem de operare , drivere și programe de aplicație. În anumite cazuri speciale părți din
software se înglobează din construcție în hardware – prin folosirea de circuite integrate
preprogramate.
În unele do menii, prin software se înțeleg în primul rând datele cu care lucrează aparatele sau
calculatoarele, cum ar fi imaginile digitalizate, sunete și piese muzicale, jocurile pentru
calculator, filme digitalizate, clipuri video și multe alte date asemănătoare. În caz extrem,
până și purtătorii fizici de date sau "mediile" sunt considerate a fi "software", ca de exemplu
discurile optice de tip CD și DVD , casetele video VHS și miniDV , casetele audio [22].
IV.1. P roces software
l Un set de activități care au ca și obiectiv dezvoltare și evoluția software -ului.
l Activitățile generice în toate procesele software sunt :
• Specificație – ceea ce trebuie ca sistemul să îndeplinească și constrângerile de
dezvoltare
• Dezvoltare – producerea sistemului software
• Validare – verificarea modului în care aplicația îndeplinește ceea ce clientul
dorește
• Evoluție – modificarea software -ului în concordanță
cu modificarea ceri nțelor [20].
IV.2 Aplicație softweare
Aplicațiile software sunt acele programe informatice care necesită un sistem de
operare pentru a putea fi utilizate. Aplicațiile software nu pot accesa direct
componentele hardware , ci doar prin intermediul funcțiilor p use la dispoziție de sistemul de
operare .
Aplicațiile software pot fi programe informatice de calcul tabelar sau editare de texte (Office,
Open Office), de editare video, de redare multimedia, de navigare pe Internet (Internet
explorer, Chrome, Firefox), d e control al proceselor tehnologice ( SCADA ).

31
Aplicațiile software sunt create în diverse limbaje de programare cu ajutorul mediilor de
dezvoltare – IDE (Integrated Development Environment) puse la dispoziție gratuit sau
contracost.
De exemplu, pentru programarea aplicațiilor software pentru sistemul de operare Android se
utilizează limbajul de programare Java[24] .

Diagrama de clase a programului este următoarea :

Figura IV.1

Acum vom exp lica clasele una câte una ,iar la final ilustrăm un test și rezultatul obținut .
Clasa Run
Clasa principală este clasa Run, aceasta are funcția main. Ca un prim pas se
inițializează resursele necesare prin apelarea constructorilor SymbolTable și
LexicalAnalyzer. Se citește numele fișierului care va fi analizat lexical într -o variabilă apoi se
apelează funcția de fixare a fișierului din LexicalAnalyzer.Se reapeleaza funcția de găsire a
unităților lexicale și de afișare a acestora (afișarea se fa ce în clasa LexicalAnalyzer) până la
obținerea unității lexicale care marchează finalul fișierului ilustrată prin tipul FINISH [23].
Rezultatul programului va fi o afișare a valorii semantice a unitățile lexicale detectate
urmat de tipul unității lexicale .

32
Clasa Symbol
Este folosită ca și template pentru a ne crea propriul nostru tip de dată.Acesta va ține minte în
ordine tipul unității lexicale,pe ce linie se află, pe ce poziție se află,valoarea semantică a
unității lexicale.
Constructorul este explicit și construiește un obiect de tipul declarat [23].
Clasa SymbolTable
Anterior acestei clase se află o enumerare TokenType.În acest mod declarăm toate tipurile de
unități lexicale posibile:
 RESERVEDWORD – cuvâ nt rezervat
 SEPARATOR – separator
 OPERATOR – operat or
 ID – identificator
 BOOLEANLITERAL – literal boolean
 NULLLITERAL – literal nul
 STRINGLITERAL – literal ș ir de caractere (string)
 CHARACTERLITERAL – literal caracter
 INTEGERLITERAL – literal î ntreg
 FLOATLITERAL – literal în virgulă lotanta
 WHITESPACE – spațiu alb
 FINISH – tipul returnat când se termină de analizat textul sursă
Această clasă are declarat un tabel de dispersie.În constructor sunt scrise manual toate
cuvintele cheie, separatorii, operatorii, literalii booleeni și literalul nul care sunt introduse
apoi în tabel.Cheia introdusă în tabel este un string care este identic cu valoarea semantică a
simbolului.Această strategie ne simplifică procesul de verificare a existenței cheilor în tabel
astfel depistând datele introduse mult mai ușor.
Sunt declarate și funcțiile :
 get – returnează obiectul de tip simbol din tabel a cărui cheie se potrivește cu
parametrul nostru
 constainsKey – verifică dacă vreo cheie din tabel este la fel cu parametrul nostru
 put – se introduce în tabelul de dispersie unitatea lexicală primită ca parametru

Clasa LexicalAnalyzer
Constructorul clasei atribuie unei variabile tabelul de dispersie .
Functia inputFileName fixează fișierul care este de prelucrat .

33
Funcția nextChar returnează următorul caracter de citit. La fieca re apelare
incrementează indicele de poziție pe linie.Este definit comportamentul pentru cazul în care s –
a terminat linia dar nu și fișierul,s -a terminat fișierul și comportamentul normal de returnare a
caracterului de procesat.
Funcția retract decrementează indicele de poziție pe linie; efectiv ne mută înapoi cu
un caracter.
Funcția fail este importantă pentru că face legătura între majoritatea stărilor din automatul
nostru.Această funcție face trecerea de la o stare ce corespunde începutului u nui unități
lexicale spre altă stare. De exemplu în program cazurile de la 0 până la 15 sunt dedicate
operatorilor și sunt în esență stări terminale. Dacă unitatea lexicală de analizat nu începe cu
simbol de operator ci cu literele corespunzătoare unui cu vânt cheie sau identificator,atunci
seria de stări din program este de la 20 la 21.
Funcția nextToken reprezintă automatul de stări.Se citește primul caracter și se fixează prima
stare să fie starea 0. Într -un ciclu infinit se procesează condițiile stărilo r și acolo unde este
cazul instrucțiunile stărilor. Acest ciclu rulează până se returnează o valoare de tip
TokenType.
Stările de la 0 la 15 sunt dedicate operatorilor.
Stările 13 si 18 sunt dedicate comentariilor;starea 13 este o stare intermediară în ace st caz.
Stările 20 si 21 sunt dedicate cuvintelor cheie,identificatorilor si a literalilor din tabelul de
dispersie. .
Stărea 30 este dedicata separatorilor .
Stările 40 si 41 sunt dedicate literalilor de tip string.
Stările 50 si 51 sunt dedicate literalilo r de tip caracter.
Stările de la 60 in sus sunt dedicate numerelor.
Stărea 99 este dedicată spațiilor albe.
Starea 100 se execută când se ajunge la finalul bandei de intrare.
Functia PrintToken afiseaza rezultatul final al programului ; tipul tokenului si va loarea
semantica.
Un ex emplu de rezultat pentru textul intodus următor este:
public static void main(String args[])
{
int a=15;
int b=0B1___01_1_0;
String b="Serbus";
char c='a'+'b';
// aiurea:
System./*sau nu*/out.println("Hello World!");
}

34

Type in the file name you wish to lexically analyze:
D:/test.txt
public –RESERVEDWORD
static –RESERVEDWORD
void–RESERVEDWORD
main –ID
(–SEPARATOR
String –ID
args–ID
[–SEPARATOR
]–SEPARATOR
)–SEPARATOR
{–SEPARATOR
int–RESERVEDWORD
a–ID
=–OPERATOR
15–INTEGERLITERAL
;–SEPARATOR
int–RESERVEDWORD
b–ID
=–OPERATOR
0B1___01_1_0 –INTEGERLITERAL
;–SEPARATOR
String –ID
b–ID
=–OPERATOR
Serbus –STRINGLITERAL
;–SEPARATOR
char–RESERVEDWORD
c–ID
=–OPERATOR
a–CHARACTERLITE RAL
+–OPERATOR
b–CHARACTERLITERAL
;–SEPARATOR
System –ID
.–SEPARATOR
out–ID
.–SEPARATOR
println –ID
(–SEPARATOR
Hello World! –STRINGLITERAL
)–SEPARATOR
;–SEPARATOR
}–SEPARATOR

35
Capitolul V Concluzii

Java este un limb aj foarte ultilizat în multiple domenii și este unul dintre puținele limbaje
care au intenția Write Once Run Anywhere . Prin această intenție se observă faptul că o dată
scris se poate ultiliza pe orice platformă sau gadget care suportă limbajul Java.
Am a les Analiza lexicală deoarece consider ca este cel mai important pas al unui compilator,
acesta fiind cel principal. Fară această etapă nu ar putea funcționa nici un compilator atat
pentru limbajul Java cât și pentru alte limbaje de programare .
Se pot cre a compilatoare proprii pentru limbaje de programare și gramatici proprii.
Analiza lexicală este importantă pentru verificarea c orectitudinii limbajului nostru si pentru
buna funcționare a oricărui compilator.
Un limbaj propriu este foarte folositor pentru că poate fi specializat.Orice programator poate
să formuleze și să programeze propriul lui limbaj de aceea am ales limbajul Java. Acesta fiind
foarte ultilizat în multiple domenii.
Expresiile regulate sunt o m etodă ușoară de definire a unităților lexical acestea fiind cel mai
des ultilizate în limbajul Java.
Un nou concept de cercetat și implementat ar putea fi realizarea unui analizor lexical global,
adică unul care s ă recunoasc ă toate limbajele de programare. Acest lucru ar fi necesar din
comoditatea de a nu instala mai multe compilatoare diferite și pentru a facilita studenții
facultății de informatică. Acest lucru mărind productivitatea și percepția studenților pentru a
înțelege și a lucra mai bine si mult mai eficient în mediile de programare. Astfel dezvoltându –
se mult mai rapid pe plan profesional.

36
Bibliografie

[1]Mircea Drăgan, Limbaje Formale și Tehnici de Compilare 19, April 2006 .
[2]Mircea Drăgan Ștefan Mărușter, Limbaje formale 23, February 2005 .
[3]http://en.wikipedia.org/wiki/Java_language Consultat la 1 4.03.2018 , 1 5.03.2018 și
16.03.2018 .
[4]http://en.wikipedia.org/wiki/Regular_expression Consultat la 10.04.2018, 11.04.2018,
12.04.2018 și 19.04.2018 .
[5]http://docs.oracle.com/javase/specs/jls/se7/html/index.html Consultat la 02.05.2018,
03.05.201 8, 04.05.2018, 05.05.2018.
[6] https://docs.oracle.com/javase/specs/jls/se7/html/jls -1.html#jls -1.1 Consultat la
02.05.2018.
[7] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html Consultat la 02.05.2018.
[8] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10.1 Consultat la
03.05.2018.
[9] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.htm l#jls-3.11 Consultat la
04.05.2018.
[10] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.12 Consultat la
04.05.2018.
[11] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.9 Consultat la
04.05.2018.
[12] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10 Consultat la
04.05.2018.
[13] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10.2 Consultat la
04.05.2018
[14] https://docs.oracle.com/javase/specs /jls/se7/html/jls -3.html#jls -3.10.3 Consultat la
05.05.2018.
[15] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10.4 Consultat la
05.05.2018.
[16] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10.5 Consultat la
06.05.2018.
[17] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.10.6 Consultat la
06.05.2018.

37
[18] https://docs.oracle.com/ javase/specs/jls/se7/html/jls -3.html#jls -3.10.7 Consultat la
06.05.2018.
[19] https://docs.oracle.com/javase/specs/jls/se7/html/jls -3.html#jls -3.5 Consultat la
07.05.2018.
[20] Notițe curs “Ingineria Program ării”, Profesor : Novac Constantin Ovidiu.
[21] https://en.wikipedia.org/wiki/Gaikai Consultat la 12.05.2018.
[22] https://ro.wikipedia.org/wiki/Software Consultat la 14.05.2018.
[23]D. Zmaranda, Programare orientată pe obiecte cu aplicații în Visual C++, Editura
Universității din Oradea, ISBN 973 -613-681-7, 2004
[24] D. Zmaranda, Elemente de programare orientată pe obiecte utilizând limbajul C++,
Editura Universității din Oradea, ISBN 973 -613-013-4, 2001
[25] D. Zmaranda, Elemente de programare orientată pe obiecte în limbajul C# – Editura
Universității din Oradea, ISBN 978 -973-759-522-5, 2008
[26] https://despretot.info/software -definitie/ Consultat la 22 .05.2018

Similar Posts