Sunteți pe pagina 1din 15

Indrumator de laborator - LUCRAREA NR.

1
Introducere Analiza lexicala
Construirea unui analizor lexical 1.1. Structura unui translator
Un translator este un program care realizeaz translatarea unui program de la intrare scris ntr-un anumit limbaj, ntr-un program echivalent de la ieire, scris ntr-un alt limbaj. ntre programul de la intrare i programul de la ieire trebuie s existe o relaie de echivalen n ceea ce privete efectul lor asupra calculatorului. Programul de la intrare trebuie s respecte anumite restricii. Respectarea acestor restricii este verificat n cadrul procesului de translaie i eventualele erori sunt semnalate prin raportare de erori. Figura 1.1.1. prezint funciile principale ale unui translator.
Translator Program de la intrare, scris ntr-un limbaj Program de la ieire, scris n alt limbaj

Raportare erori

Figura 1.1.1. Funciile principale ale unui translator

Programul de la intrare poate fi scris ntr-un limbaj de nivel nalt, numit limbaj surs, iar programul de la ieire poate fi scris ntr-un limbaj main, numit limbaj obiect. Dac limbajul de la intrare este un limbaj de nivel nalt, iar limbajul de la ieire este un limbaj apropiat de limbajul main, translatorul se numete compilator. Compilatorul este un translator care traduce instruciuni de nivel nalt n cod main. Un translator execut o succesiune de operaii asupra programului surs i l transform n reprezentri din ce n ce mai apropiate de limbajul destinaie. Din acest motiv, procesul de translaie se divide ntr-o serie de faze. O faz este o operaie unitar n cadrul creia are loc transformarea programului surs din reprezentarea iniial ntr-o reprezentare echivalent. n figura 1.1.2 se reprezint schema bloc a unui translator. Examinnd aceast figur, se observ la intrare programul surs, iar la ieire programul obiect.

Cod surs Gestiune caractere

Faz analitic (Front end)

Analizor lexical (Scanner) Atomi Analizor sintactic (Parser) Arbore sintactic Analizor semantic Gestiune tabele

Arbore sintactic adnotat Generator de cod intermediar Faz sintetic (Back end) Raportare erori

Optimizator de cod

Generator de cod final

Cod obiect

Figura 1.1.2. Schema bloc a unui translator

n primele etape ale procesului de translaie, pe lng transformri aplicate asupra limbajului de la intrare se face i o analiz a acestuia, care const n verificarea respectrii restriciilor impuse limbajului.Dac restriciile sunt respectate, se genereaz codul obiect, iar n caz contrar se genereaz mesaje de eroare. n acest context, procesul de translatare se divide ntr-o faz analitic, urmat de o faz sintetic. n faza analitic se analizeaz programul surs i se determin dac el corespunde cu restriciile impuse de limbajul surs, iar n faza sintetic se genereaz efectiv codul obiect. Componentele translatorului care ndeplinesc aceste faze majore se mai numesc i "front end" i "back end". Fiecare din aceste faze, conine la rndul ei alte componente. Acestea sunt reprezentate n figura 1.1.2. Blocul de gestionare caractere. Acest bloc comunic exteriorul, prin sistemul de operare, pentru preluarea caracterelor din textul surs. De cele mai multe ori, aceast parte a translatorului este inclus n analizorul lexical. Analizorul lexical (numit i scaner). Acest bloc preia textul surs sub forma unei secvene continue de caractere pe care le grupeaz n entiti numite atomi. Atomii primesc coduri lexicale, astfel c, la ieirea acestei faze, programul surs apare ca o secven de coduri. Exemple de atomi: cuvinte cheie, identificatori, constante numerice, semne de punctuaie etc. Analizorul lexical realizeaz i verificarea corectitudinii programului de la intrare din punct de vedere lexical.
2

Analizorul sintactic (numit i parser) are ca scop verificarea corectitidinii programului de la intrare din punct de vedere sintactic i gruparea atomilor rezultai n urma analizei lexicale n structuri sintactice. O structur sintactic poate fi un arbore n care nodurile terminale reprezint atomi, iar nodurile interioare reprezint iruri de atomi care formeaz o entitate logic. Exemple de structuri sintactice: expresii, instruciuni, declaraii etc. Analiza semantic este urmtoarea faz a procesului de compilare care efectueaz verificri legate de: - compatibilitatea tipurilor datelor cu operaiile n care ele sunt implicate - respectarea regulilor de vizibilitate impuse de limbajul surs. Analizorul semantic adaug informaii suplimentare la arborele sintactic produs n etapa precedent, informaii numite atribute i produce un arbore sintactic adnotat. Atributele sunt informaii suplimentare produse de analizorul semantic. Generatorul de cod intermediar. n aceast faz are loc transformarea arborelui sintactic ntr-o secven de instruciuni simple, similare macroinstruciunilor unui limbaj de asamblare. Diferena dintre codul intermediar i un limbaj de asamblare este n principal aceea c, n codul intermediar nu se specific registrele utilizate n operaii. Exemple de reprezentri pentru codul intermediar: notaia postfix, instruciunile cu trei adrese etc. Codul intermediar prezint avantajul de a fi mai uor de optimizat dect codul main. n plus, deoarece el se refer la o main abstract, asigur o portabilitate mai bun a translatorului. Optimizatorul de cod este o faz opional, care are rolul de a modifica poriuni din codul intermediar generat, astfel nct programul rezultat s satisfac anumite criterii de performan viznd timpul de execuie i/sau spaiul de memorie ocupat. Generatorul de cod final. Aceast faz transform instruciunile scrise n cod intermediar (eventual optimizat) n instruciuni main (sau de asamblare) pentru calculatorul int (cel pe care se va executa programul compilat). n afar de blocurile enumerate mai sus, procesul de compilare mai include urmtoarele: Gestionarea tabelei de simboluri. Tabela de simboluri (TS) este o structur de date special, destinat pstrrii de informaii despre simbolurile (identificatorii) care apar n programul surs; compilatorul face referire la aceast tabel aproape n toate fazele compilrii. Tratarea erorilor. Un compilator trebuie s fie capabil s recunoasc anumite categorii de erori care pot s apar n programul surs. Tratarea unei erori presupune: - detectarea ei; - emiterea unui mesaj corespunztor; - revenirea din eroare, adic, pe ct posibil, continuarea procesului de compilare pn la epuizarea textului surs, astfel nct numrul de compilri necesare eliminrii tuturor erorilor dintr-un program s fie ct mai mic. Exist erori specifice de compilare pentru fiecare etap din faza analitic (sau de frontend). Dup aceast faz, practic nu se mai detecteaz erori de compilare i se genereaz n mod sigur un cod obiect. Verificarea corectitudinii acestuia din punct de vedere logic nu mai este sarcina compilatorului. Aceasta se realizeaz de ctre programator folosind diferite strategii de test.

1.2. Analiza lexical


Construirea unui analizor lexical Analizorul lexical reprezint interfaa dintre programul surs i compilator. El realizeaz parcurgerea textului surs de intrare, caracter cu caracter i grupeaz aceste caractere n entiti logice numite atomi (tokens). Figura 1.2.1. prezint schematic funcia esenial a unui analizor lexical.
Program surs Analizor lexical Atomi lexicali

Figura 1.2.1. Funcia unui analizor lexical

Deoarece textul surs este parcurs caracter cu caracter, analizorul lexical are un timp de execuie mai mare raportat la celelalte elemente ale unui compilator, care vor avea la intrare reprezentri mai compacte ale programului de la intrare. Un analizor lexical trebuie s aib n vedere urmtoarele aciuni: 1. Eliminarea spaiilor ( blankuri, tabulatori, etc.); 2. Eliminarea comentariilor; 3. Gruparea caracterelor n atomi i identificarea clasei pentru fiecare atom; 4. Generarea atributelor i scrierea n tabela de simboluri atunci cnd e cazul. Se numete lexem, un ir de caractere de la intrare care este n curs de analizare. Iniial, lexema curent este irul vid. La ea se adaug pe rnd caractere de la intrare, pn cnd va corespunde cu un atom al limbajului, ori se va semnala eroare prin epuizarea tuturor posibilitilor. Atomii se mpart n mai multe categorii, numite clase de atomi. Clasele de atomi ntlnite n majoritatea limbajelor de programare sunt: identificatori, cuvinte cheie, constante numerice (ntregi, reale, eventual reprezentate n diferite baze de numeratie), operatori (aritmetici, logici, relationali), semne de punctuatie, delimitatori, constante de tip caracter, respectiv ir de caractere, comentarii. Pentru exemplificare, se consider urmtoarea secven de la intrare:
do { i++; }while (i<10);

Atomii din aceast secven sunt prezentai n figura 1.2.2.

Program surs
do { i++; }while (i<9); d o \n {

Gestionare caractere

\n

\n

<

Analizor lexical

cuv.cheie do

semn pct {

id i

op ++

semn pct ;

semn pct }

cuv.cheie while

semn.pct (

id i

op <

numar 9

Semn pct ++

Semn pct ;

Figura 1.2.2. Atomii din secvena de intrare exemplu.

Pentru fiecare atom ntlnit, analizorul lexical furnizeaz un dublet de forma: <CodLexical, atribut>. Codul lexical servete la identificarea clasei de care aparine atomul, iar atributul identific atomul n cadrul clasei (vezi figura 1.2.3.)
Cod
Cod lexical Atribut

Adresa

Valoarea

Figura 1.2.3.

Atributul nu este prezent n toate cazurile. El conine informaii suplimentare: valoarea atomului, dac acesta este de tip numeric; adresa unde se memoreaz, n cazul n care atomul este un identificator.

Codul lexical este un numr ntreg care identific atomul i care este stabilit astfel: Pentru clase de atomi cu un numr cunoscut de elemente, fiecare atom este asociat cu un numr distinct, care identific complet atomul. n aceste cazuri prezena atributului nu este necesar. - Pentru clase de atomi cu un numr posibil infinit de elemente, codul este un cmp care identific clasa, el fiind acelai pentru toi atomii clasei respective. n aceste cazuri, codul este urmat obligatoriu de un atribut. Modul n care se aleg i se ataeaz codurile lexicale este la latitudinea proiectantului.
cuvnt cheie begin clasa identificator alfa clasa atribut Atomul numeric 5 clasa atribut
200 adresa

Cod
100

Pointeaz spre tabela de simboluri unde s-a memorat identificatorul alfa

300 5

Figura 1.2.4. Exemplu de coduri lexicale 5

Un analizor lexical poate fi construit fie manual, fie folosind instrumente software, numite generatoare de analizoare lexicale. Un generator de analizoare lexicale este un program care primete la intrare, ntr-un limbaj de specificare, structura atomilor lexicali i eventualele aciuni care vor trebui executate simultan cu analiza lexical. Ieirea unui astfel de program este un program de analiz lexical. Comunicarea analizorului lexical cu celelalte componente ale compilatorului Analizorul lexical comunic cu tabela de simboluri i cu analizorul sintactic. Comunicaia cu tabela de simboluri presupune operaii de scriere a codului pentru identificatori. Pentru comunicaia cu analizorul sintactic, analizorul lexical poate folosi unul din urmtoarele procedee: a. Analiza lexical se execut ntr-o trecere separat i produce la ieire codul tuturor atomilor din programul surs, care se poate scrie ntr-un fiier, ori se poate pstra n memorie. b. Analizorul sintactic apeleaz analizorul lexical n momentul n care are nevoie de un nou atom. La fiecare apel, analizorul lexical trimite un singur atom la intrarea analizorului sintactic. Aceast implementare este mai avantajoas, deoarece nu se mai produce o form codificat a programului surs. c. Cele dou analizoare funcioneaz n regim de corutin, fiind simultan active.

Uzual, analizorul lexical este apelat de analizorul sintactic. Analizorul lexical poate s returneze codul lexical al atomului, iar atributele lui pot fi variabile globale, vizibile n alte pri ale compilatorului. Construirea manual a unui analizor lexical folosind metoda automatului finit Descrierea atomilor limbajului surs se transform ntr-o diagram de tranziie care constituie reprezentarea grafic a unui automat finit determinist de recunoatere. Proiectarea analizorului lexical n acest caz se reduce la scrierea unei proceduri care s simuleze trecerea automatului dintr-o stare n alta, pe msur ce se parcurge textul de intrare, pn cnd se ajunge ntr-o stare final (de recunoatere). Trecerile prin diferite stri vor fi nsoite, dup caz, de execuia unor rutine semantice corespunztoare. Metoda manual asigur creerea unor analizoare lexicale eficiente, dar scrierea programului e monoton i prezint riscul unor erori, mai ales dac exist un numr mare de stri. Gestionarea textului surs Textul surs se citete linie cu linie, iar pentru memorarea unei linii se folosete o zon tampon (buffer), a crui dimensiune corespunde cu lungimea fizic a liniei de intrare. Sfritul textului surs este marcat de EOF. Pentu a localiza un atom lexical (lexema curent), se pot folosi doi pointeri, numii pointer de nceput pi i pointer de anticipare pa. La nceput, ambii pointeri pi i pa indic primul caracter al lexemei curente. n continuare, pointerul pa avanseaz, pn cnd analizorul identific atomul. n acest moment, irul de caractere cuprins ntre cei doi pointeri este chiar atomul lexical identificat. Dup prelucrarea lexemei curente, pi este adus n aceeai poziie cu pointerul de anticipare i se continu cu analiza unui nou atom.
6

n figura 1.2.5. se reprezint felul n care se folosesc cei doi pointeri pentru identificarea unui atom. Dup detectarea unui atom, cei doi pointeri se pot poziiona fie pe ultimul caracter al lexemei curente, fie pe primul caracter al lexemei urmtoare. n a doua situaie, aa cum se va observa n continuare, nu mai este necesar returnarea la intrare a unui extracater pentru recunoaterea anumitor atomi.
b e pi pa
b pi b e g i n e g i n \n pa \n x : = 1 ; x : = 1 ;

\n

pi pa

Figura 1.2.5. Folosirea a doi pointeri pentru identificarea unui atom

Construirea diagramelor de tranziii Diagramele de tranziii conin: O mulime de stri, reprezentate cu cercuri; Starea final este cea n care s-a recunoscut un atom; ea este reprezentat cu 2 cercuri concentrice; - Arcele reprezint tranziiile analizorului dintr-o stare n alta. Arcele ncep ntr-o stare i se pot termina n aceeai stare, ori ntr-o alt stare; - Arcele sunt etichetate cu simboluri, care indic ce caracter de la intrare determin trecerea analizorului din starea de la care pornete arcul n starea n care ajunge arcul.

Aceste diagrame de tranziii sunt asociate cu automate cu stri finite, care vor fi prezentate n detaliu ntr-un capitol urmtor. n acest capitol se va folosi o reprezentare intuitiv a acestora. Proiectarea analizorului lexical n acest caz se reduce la scrierea unei proceduri care s simuleze trecerea automatului dintr-o stare n alta, pe msur ce se parcurge textul de intrare, pn cnd se ajunge ntr-o stare final (acceptoare, sau de recunoatere). Trecerile prin diferite stri vor fi insoite, dup caz, de execuia unor rutine semantice corespunztoare. Simularea diagramei de tranziie se poate realiza in dou moduri: a. Prin cod. n acest caz, tranziiile ntre stri se transcriu sub form de cod. De obicei se utilizeaz o instruciune de selecie (de tip "case" sau "switch") care, n funcie de starea curent i de caracterul curent de intrare, determin starea urmtoare i apeleaz rutina semantic ataat. b. Prin structuri de date. n acest caz diagrama de tranziii se transpune sub forma unei structuri de date tabelare, iar accesul la elementele acestei structuri se obine pe baza strii curente i a caracterului curent de intrare. Fiecare element al tabelului indic starea urmtoare precum i rutina semantic ataat tranziiei respective.

Exemplul 1. n acest exemplu se va prezenta felul n care se realizeaz diagramele de tranziii pentru un analizor lexical de tip automat finit determinist care recunoate un numr redus de atomi de tipul urmtor: - Cuvinte cheie; - Identificatori; - Numere ntregi; - Operatori i separatori:":=","{","}", "(", ")","+", "-","=", ";". Pentru fiecare tip de atom se construiete o diagram de tranziie elementar, care are o stare iniial marcat cu o sgeat de intrare neetichetat i o stare final, reprezentat cu dou cercuri concentrice, n care s-a recunoscut atomul respectiv. Srile automatelor sunt numerotate. Diagramele de tranziii sunt reprezentate n figura 1.2.6. Pentru cuvinte cheie nu se construiesc diagrame de tranziii, deoarece iniial analizorul lexical le poate considera identificatori, decizia de apartenen la clasa cuvintelor fcndu-se de exemplu prin cutarea ntr-o tabel de cuvinte cheie. De asemenea, automatul pentru identificatori este prezentat ntr-o form simplificat. Uneori, de exemplu pentru atomul "{", atomul e recunoscut imediat prin citirea ultimului caracter din acesta. Pentru ali atomi ns, de exemplu pentru numar, se cunoate lungimea atomului numai dup citirea unui extracaracter, care nu aparine numrului (aceast situaie apare n toate strile notate cu *). n acest caz, caracterul citit n plus trebuie returnat la intrare. Dac se citete un caracter care nu corespunde cu nici o secven acceptat, se returneaz atomul special eroare. Strile iniiale ale fiecrei diagrame se reunesc ntr-o singur stare iniial, care poate fi referit n continuare ca "START". Aceasta semnific faptul c nu s-a decis nc ce diagram se va urma. Alegerea diagramei se face pe baza caracterului de la intrare.
1 digit digit 4 letter 5 not(letter|digit) 6* 2 not(digit) 3*

letter|digit 7 : 8 = 9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Figura 1.2.6. Automatele elementare corespunztoare cu atomii din exemplul 2.1.

Automatul are o mulime de stri finale, care din motive de simplitate se pot reuni ntr-o singur stare, numit GATA.

Exemplul 2. Acest exemplu i propune s prezinte o modalitate de implementare a unui analizor lexical pentru un limbaj care posed urmtoarele simboluri de baz: - Identificatori; - Cuvinte cheie: begin, end; - Constante numerice: numere ntregi pozitive; - Caractere speciale: ;; - Operatori: =; - Cometarii: marcate de {}. Operaiile care vor fi efectuate de analizorul lexical sunt: eliminarea spaiilor i a comentariilor; colectarea identificatorilor i a cuvintelor cheie; colectarea numerelor; altele. Etapele de implementare a analizorului lexical sunt urmtoarele: - Definirea simbolurilor de baz
identificator litera cifra cuvant_cheie nr_intreg delimit ::= operator coment spatii_albe ::= blank | tab | CR\LF =
*

::= litera (_| litera | cifra ) ::= A . . Z | a . . z ::= 0 . . 9 ::= and | begin ::= nr_baza10 ::= ;

::= { ( caracter_tiparibil | spatii_albe )

Realizarea diagramelor de tranziie. n figura 1.2.7. sunt prezentate diagramele de tranziie pentru cteva tipuri de atomi.

litera |cifra|_

Start 0

litera 1

Altceva

cifra

Start 0

cifra 3

Altceva

Start

= 5 6

Figura 1.2.7. Diagramele de tranziie pentru atomi din exemplul 2.

Eticheta special Altceva care eticheteaz un arc care iese dintr-o stare, semnific un caracter de la intrare diferit de simbolurile care eticheteaz celelalte arce care ies din acea stare. Implementarea analizorului lexical manual pe baza diagramelor de tranzitie. Analizorul lexical furnizeaza analizorului sintactic urmtoarul tip de nregistrare:
atom: record codlexical atribut end

procedura AnalizaLexicala(*fisierul de intrare;atom) *initializare atom *elimina spatiile albe daca caracterul curect este litera atunci *retine literele, cifrele si _ care formeaza identificatorul *verifica daca este cuvant cheie *codifica corespunzator atomul *retine numele identificatorului sfdaca altfel daca caracterul este cifra atunci *retine numarul intreg *codifica constanta intreaga *retine reprezentarea externa a constantei sfdaca altfel daca caracterul = atunci *retine operatorul de egalitate *codifica operatorul de egalitate sfdaca altfel daca caracterul ; atunci *retine punctsivirgula *codifica punctsivirgula sfdaca altfel daca caracterul EOF atunci *codifica atomul ca fiind de sfarsit sfdaca

10

return

altfel *codifica atomul ca eronat

n continuare se prezint clasele necesare unei implementri a unui analizor lexical n limbajul C++. TCod: tip enumerare care contine constante pentru codificarea fiecarui atribut simbol CPos: clasa cu informatii legate de poziia unui atribut n fiierul de intrare linie: linia col: coloana pathName: calea fiierului de pe disc CAtom: clasa cu informaii despre simbolul analizat cod: cod simbol de tip TCod pozitia: poziia simbolului n fiier atribut: numele simbolului CScanner: clasa pentru analiza lexical fisier: fiierul de intrare ch: caracterul curent citit din fiier name: nume fiier atom: simbol obiect CAtom CitesteCh: citete un caracter din fiier i elimin spaiile albe (space, tab, enter, etc.) AtomUrm: metoda care impementeaz analiza lexical Decodificare: decodofic atributul gsit. Pe baza claselor prezentate se realizeaz implementarea programului.
#include #include #include #include <stdio.h> <conio.h> <string.h> <fstream.h>

#include <ctype.h>
#include <iostream.h> #include <stdlib.h> typedef enum { CID, CBEGIN, CEND, CNRINTREG, CEGAL, CPCTV, CBAD, CEOF }TCod; class CPos { public: unsigned int line; unsigned int col; char* pathName; CPos(); ~CPos(); }; CPos::CPos() { line = 0; col = 0; pathName = ""; }

11

CPos::~CPos() { } class CAtom { public: TCod cod; CPos pozitia; char* atribut; }; class CScanner { public: ifstream fisier; int ch; char* name; CAtom atom; CScanner(char* fis); ~CScanner(); CAtom AtomUrm(); int CitesteCh(int c); char* Decodificare(int i); }; CScanner::CScanner(char* fis) { const char *p; p = fis; fisier.open(p); if(!fisier) { cout<<"Nu se poate deschide fisierul\n"; return; } name = fis; ch = ' '; } CScanner::~CScanner() { fisier.close(); } char* CScanner::Decodificare(int { char* Nume; switch(i) { case CID: Nume case CBEGIN: Nume case CEND: Nume case CNRINTREG: Nume case CEGAL: Nume case CPCTV: Nume case CBAD: Nume case CEOF: Nume } return Nume; } int CScanner::CitesteCh(int c) i)

= = = = = = = =

"Identificator";break; "Cuvant cheie BEGIN"; break; "Cuvant cheie END"; break; "Numar intreg"; break; "Operator de atribuire ="; break; "Delimitator ;";break; "bad";break; "eof";break;

12

c++; ch = fisier.get(); if(ch == '\n' || ch == '\r') { atom.pozitia.line++; //elimina enter c = 0; } if(ch == '\t') c = (c/8+1)*8; //elimina tab de 8 spatii return c;

CAtom CScanner::AtomUrm() { static int c = 0; atom.cod = CBAD; atom.pozitia.pathName=name; atom.pozitia.col = c; char* ch_string; strcpy(atom.atribut, ""); //elimina spatiile albe while(isspace(ch)) { if(ch == ' ') c++; if(ch == '\n' || ch == '\r') { atom.pozitia.line++; c = 0; } if(ch == '\t') c = (c/8+1)*8; ch = fisier.get(); } //verifica daca este comentariu if (ch == '{') { atom.atribut = ""; while (ch != '}') { c = CitesteCh(c); } ch = fisier.get(); } else //verifica daca este identificator if(isalpha(ch)) { ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c = CitesteCh(c); atom.pozitia.col++; while (isalnum(ch) || ch == '_') { ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c = CitesteCh(c); } //verifica daca e cuvant cheie "begin" if(strcmp(atom.atribut,"begin") == 0)

13

else

atom.cod = CBEGIN; if(strcmp(atom.atribut,"end") == 0) atom.cod = CEND; else atom.cod = CID;

} //verifica daca este numar intreg poz. else if (isdigit(ch)) { ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c = CitesteCh(c); atom.pozitia.col++; while (isdigit(ch)) { ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c = CitesteCh(c); } atom.cod = CNRINTREG; } //verifica daca este operator else if (ch == '=') { atom.cod = CEGAL; ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c++; atom.pozitia.col = c; ch = fisier.get(); } //verifica daca este operator de delimitare else if (ch == ';') { atom.cod = CPCTV; ch_string = (char*)&ch; strcat(atom.atribut, ch_string); c++; atom.pozitia.col = c; ch = fisier.get(); } else if (ch == EOF) { atom.cod = CEOF; atom.atribut = ""; c++; atom.pozitia.col = c; } return atom; } int main() { clrscr(); CScanner ALex("alex.txt"); CAtom t; do

14

t = ALex.AtomUrm(); if(t.atribut != "") { cout<<t.atribut<<"\t"<<ALex.Decodificare(t.cod); cout<<"\n"; getch(); } }while(strcmp(ALex.Decodificare(t.cod), "eof") != 0); getch(); return 0; }

Tema de laborator:
S se implementeze un analizor lexical pentru urmtoarele simboluri de baz:
liter cifr identificator cuvnt_cheie ::= A . . Z | a . . z ::= 0 . . 9 ::= liter ( _|liter | cifr_zec )* ::= and | begin | case | char | const | div | do | downto | else | end | for | function | if | integer | mod | not | of | or | procedure | program | real | repeat | then | until | var | while ::= nr_intreg | nr_real ::= nr_baza10 ::= ( cifr_zec )+ ::= nr_baza10 . nr_baza10 ::= ; | . | , | : | .. ::= + | - | * | / | ( | ) | [ | ] | < | <= | > | >= | <> | = | := ::= { ( caracter_tipribil | spaii_albe )* } ::= blank | tab | CR\LF ::= " ( caracter_tipribil | blank )* " ::= ' caracter_tipribil | blank '

const_num nr_intreg nr_baza10 nr_real delimit operator coment spaii_albe const_ir const_char

15

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