Documente Academic
Documente Profesional
Documente Cultură
Exerciții și aplicații
1. Obiective
Scopul acestei lucrări de laborator îl constituie deprinderea noţiunilor
fundamentale legate de limbajele formale şi a abilităţilor de lucru cu acestea în
contextul rezolvării de probleme practice. În urma parcurgerii acestei lucrări
studentul:
va şti ce este un alfabet, un cuvânt, un limbaj, o gramatică, şi care este
legătura dintre acestea;
va cunoaşte particularităţile limbajelor care aparţin clasei limbajelor
regulate;
va cunoaşte particularităţile gramaticilor regulate şi va putea descrie
diverse limbaje regulate folosind astfel de gramatici;
va şti ce este o expresie regulată şi va putea să descrie diverse limbaje
regulate folosind astfel de expresii;
va putea folosi utilitare de căutare după model de genul grep;
va şti să implementeze software căutări după model folosind expresii
regulate.
2. Breviar teoretic
Se prezintă în continuare principalele noţiuni teoretice necesare înţelegerii
prezentei lucrări de laborator. (A se vedea şi lucrările [1]-[5].)
2.3. Gramatici
O gramatică ne arată nişte reguli cu ajutorul cărora putem să generăm
cuvinte.
8
Exemplu de gramatică: X | 0X, unde este cuvântul vid, 0 este un
simbol şi X este o variabilă. X este în acest caz şi variabilă de start (adică variabila
de la care se începe generarea). Citim regula de mai sus ca “X produce (sau
generează) sau 0X”. (Producţia (sau regula) aceasta este de fapt o formă
compactă de scriere a următoarelor două producţii: (1) X şi (2) X 0X.)
Un exemplu de utilizare a acestei gramatici pentru a genera cuvinte este reprezentat
în Figura 1.
O gramatică este, aşadar, un set de producţii (sau reguli de generare) care
descriu modalităţile posibile de a obţine cuvintele unui limbaj prin înlocuiri
succesive ale variabilelor pornind de la variabila de start. (Mai exact, se înlocuieşte
capul producţiei (adică ceea ce este în stânga semnului “ ”) cu corpul producţiei
(adică ceea ce este în dreapta semnului “ ”).)
9
În particular, o gramatică regulată este o gramatică ce este fie de tip
liniară la dreapta, fie de tip liniară la stînga.
În partea dreaptă a producţiilor unei gramatici liniare la dreapta poate să
apară maxim o variabilă şi dacă apare să fie situată pe ultima poziţie.
Exemplu de gramatică regulată liniară la dreapta:
X aY
Y | aY
În partea dreaptă a producţiilor unei gramatici liniare la stânga poate să
apară maxim o variabilă şi dacă apare să fie situată pe prima poziţie.
Exemplu de gramatică regulată liniară la stânga:
X Ya
Y |Ya
2.5. Grep
Utilitarul grep permite căutarea de text după model, specificarea modelului
căutat făcându-se cu ajutorul unei expresii regulate. Se găseşte în sistemul de
10
operare Linux, dar există şi versiuni pentru Windows, cum este WinGrep.
11
3. Exemple şi probleme rezolvate
Se vor studia şi reface următoarele probleme rezolvate, în scopul unei bune
înţelegeri a lor.
Soluție:
Cuvintele ce conţin cel puţin un a şi un b sunt de forma
... a ... b ...
sau
... b ... a ...
unde “...” înseamnă orice cuvânt format cu simboluri din mulţimea {a, b, c}.
Conform afirmaţiei de mai sus, expresia cerută este
(a+b+c)*a(a+b+c)*b(a+b+c)* +
(a+b+c)*b(a+b+c)*a(a+b+c)*
unde (a+b+c)* înseamnă că fie simbolul a, fie simbolul b, fie simbolul c poate
apărea de 0 ori (niciodată), o dată, de două ori, etc. (la fiecare pas putând apărea
oricare dintre ele).
Soluție:
Cuvintele cerute la această problemă sunt de forma “0 sau 1, repetat de un număr
nespecificat de ori, urmat de 1, urmat de 0 sau 1, urmat de 0 sau 1”. Înseamnă că
expresia căutată este
(0+1)*1(0+1)(0+1)
Testarea cu grep se poate face astfel
egrep '[01]*1[01][01] ex2.txt'
Rezultatul testării aceste expresii este ilustrat in Figura 3.
Soluție:
Cerinţa problemei ne indică faptul că cuvântul căutat conţine ori 3 zerouri, ori 6
zerouri, ori..., ori 3k zerouri, adică un număr de zerouri care e multiplu de 3.Între
aceste zerouri se pot afla oricâţi de 1.
Înseamnă că expresia căutată este următoarea:
14
(1*01*01*01*)*
Expresia de test în grep se scrie în felul următor:
egrep '(1*01*01*01*)+' ex4.txt
Rezultatul căutării este prezentat în Figura 5.
Soluție:
Scriem numerele 40 si 48 în binar:
40(10) = 101000(2)
48(10) = 110000(2)
Înseamnă că limbajul L este format din următoarele cuvinte:
L = {101001, 101010, 101011, 101100, 101101, 101110, 101111}.
Cum limbajul L este finit, cea mai simplă metodă de a scrie o expresie regulată
pentru a descrie cuvintele din el este să punem “+” între toate cuvintele sale. La o
privire mai atentă asupra cuvintelor limbajului observăm că acestea nu sunt
complet independente, ci respectă un model:
Primele 3 simboluri sunt 101.
Ultimele 3 simboluri sunt orice combinaţie de 0 şi 1.
Rezultă că expresia regulată pentru limbajul L este:
101(0+1)(0+1)(0+1)
Transcrierea acestei expresii în formatul recunoscut de grep se poate face în felul
următor:
egrep ‘101[01][01][01]’ ex5.txt
Testarea ei rămâne ca exerciţiu.
15
Soluție:
Identificatorii din limbajul C (sau Java, sau C#) respectă următoarele reguli:
încep cu literă (mică sau mare) sau cu simbolul “_” (underline)
şi pot avea apoi litere, cifre sau “_”.
Expresia regulată pentru limbajul acestor identificatori este, aşadar
(a+b+...+z+A+...+Z+_)+(a+b+...+z+A+...+Z+0+1+...+9+_)*
Această expresie poate fi transcrisă în formatul recunoscut de grep astfel
egrep ‘[a-zA-Z_][a-zA-Z0-9_]*’ ex6.txt
Soluția 1:
Implementăm un program în C# care realizează următoarele:
testează dacă string-ul introdus este format numai din 0 şi 1 prin utilizarea
metodei IsMatch din clasa RegEx care primeşte ca parametri string-ul şi
pattern-ul “^[0-1]+$”
şi dacă string-ul corespunde condiţiei, testează dacă antepenultimul simbol
este 1.
16
Soluția 2:
Implementăm un program similar în Java. Codul sursă este următorul:
17
18
În Figura 6 sunt arătate câteva rezultate ale rulării programului.
Soluție:
Realizăm programul în Gtk# pe platforma Mono din Linux. Interfaţa grafică va
conţine o arie de text în care putem scrie string-ul şi un buton la apăsarea căruia
19
suntem anunţaţi dacă string-ul respectiv reprezintă sau nu un identificator valid în
limbajul C.
Validitatea identificatorilor se testează folosind metoda statică IsMatch din clasa
RegEx, iar expresia de test este similară celei de la Problema 6:
^[a-zA-Z_][a-zA-Z0-9_]*
20
21
Exemple de rulare a programului sunt arătate în Figura 7.
Soluție:
Realizăm programul în C# sub Linux folosind Gtk#. Validarea cuvântului şi a
expresiei introduse de la tastatură impune ca acestea să nu conţină decât
simbolurile 0, 1, + şi * şi se realizează cu metoda IsMatch din clasa RegEx ce
primeşte ca parametri string-ul de verificat şi pattern-ul “^[0-1+*]+$”. Compararea
dintre cuvântul şi expresia regulată introduse de la tastatură se face apoi prin
aceeaşi metodă.
22
23
24
25
26
Rezultate ale rulării programului sunt arătate în Figura 8.
27
4. Desfăşurare
1. Să se parcurgă pas cu pas toate problemele rezolvate prezentate
anterior. (Pentru sistemele care nu au Linux se va folosi în loc de grep
aplicatia wingrep. Pentru problemele care necesită programare, se pot
folosi pentru sistemele cu Windows aplicaţiile Code::Blocks (pentru
C/C++) sau NetBeans (pentru Java).)
2. Pentru problemele de la 1 la 5 să se construiasca pentru respectivul
limbaj o gramatică regulată: (1) linară la stânga; (2) liniară la dreapta.
3. Pentru problema 6 o gramaticî independentă de context a fost dată în
breviarul teoretic. Să se construiască o gramatică regulată.
4. Să se scrie un program care rezolvă problema 7 fără să folosească
funcţii de bibliotecă pentru recunoaşterea expresiilor regulate.
(Limbajul de programare utilizat este la alegere.)
5. Să se scrie un program care rezolvă problema 8 fără să folosească
funcţii de bibliotecă pentru recunoaşterea expresiilor regulate.
(Limbajul de programare utilizat este la alegere.)
6. Să se scrie un program care rezolvă problema 9 fără să folosească
funcţii de bibliotecă pentru recunoaşterea expresiilor regulate.
(Limbajul de programare utilizat este la alegere.)
7. Cât de mult s-ar complica exerciţiul anterior dacă s-ar cere
recunoaşterea oricărei expresii regulate (folosind simbolurile 0 şi 1,
operatorii + şi *, precum şi parantezele rotunde)?
28