Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
lfa:2024:proiect [2024/10/24 16:56]
pdmatei created
lfa:2024:proiect [2024/11/03 22:49] (current)
cata_chiru
Line 1: Line 1:
-Deadline etapa 1: 22 nov 2023 23:59+Deadline etapa 1: 21 nov 2024 23:55
  
  
Line 8: Line 8:
 Proiectul este structurat in trei teme al caror obiectiv final reprezinta implementarea unui lexer in Python. Proiectul este structurat in trei teme al caror obiectiv final reprezinta implementarea unui lexer in Python.
 ===== Ce este un lexer? ==== ===== Ce este un lexer? ====
-Un lexer este un program care imparte un sir de caractere in subsiruri ​numite ​//lexeme//fiecare dintre ​acestea fiind clasificat ca un //token//, pe baza unei specificatii.+ 
 +Un lexer este un program care, pe baza unei specificatii, ​imparte un sir de caractere in subsiruri, si identifica carei //categorii// apartine ​fiecare dintre ​subsiruri. Categoriile se numesc ​//tokens// iar subsirurile - //lexeme//. Acest procesdeseori implementat ca prima etapa din cadrul unui parser, se numeste **analiza lexicala**.
  
 ==== Care este input-ul unui lexer? ==== ==== Care este input-ul unui lexer? ====
-Lexer-ul primeste initial o specificatie de forma:+ 
 +Specificatia unui lexer arata astfel:
 <​code>​ <​code>​
 TOKEN1 : REGEX1; TOKEN1 : REGEX1;
Line 21: Line 23:
 ... ...
 </​code>​ </​code>​
-unde fiecare ​''​TOKENi''​ este un nume dat unui token, iar ''​REGEXi'' ​este un regex ce descrie lexemele ce pot fi clasificate ca acel token. ​Puteti imagina aceasta specificatie ca un //fisier de configurare//care descrie modul in care va functiona lexerul pe diverse fisiere ​de text.+unde fiecarui ​''​TOKENi'' ​ii este asociat ​un ''​REGEXi'' ​care descrie ​toate lexemele ce trebuie ​clasificate ca acel token. ​Specificatia de mai sus are caracterul unei //configuratii// care descrie modul in care orice sir de la input ar trebui analizat lexical ​de catre lexer.
  
-Inputul efectiv al unui lexer este un text care va fi impartit in lexeme folosind expresii regulate. In cursurile viitoare veti afla mai multe detalii despre cum functioneaza si cum sunt implementate lexerele.+Inputul efectiv al unui lexer este un text care va fi obiectul analizei lexicale.
  
 ==== Care este output-ul unui lexer? ==== ==== Care este output-ul unui lexer? ====
-Lexer-ul are ca output o lista de forma : ''​[(lexema1, ​TOKEN_LEXEMA_1), (lexema2, ​TOKEN_LEXEMA_2), ...]'',​ unde ''​TOKEN_LEXEMA_N''​ este numele token-ului asociat lexemei ​n, pe baza specificatiei.+Lexer-ul are ca output o lista de forma : ''​[(lexema1, ​TOKEN_i1), (lexema2, ​TOKEN_i2), ...]'',​ unde ''​TOKEN_iN''​ este numele token-ului asociat lexemei ​N, pe baza specificatiei.
  
 ===== Etapa 1 ===== ===== Etapa 1 =====
-Datorita dificultatii lucrului direct cu regex-uri pentru verificarea apartenentei unui cuvant in limbaj, lexerele reale trec prin cateva etape intermediare inainte de inceperea analizei textului. Aceste etape construiesc un DFA pe baza regex-ului. 
  
-**Etapa 1** a proiectului consta in conversia ​NFA in DFA (folosind ​Algoritmul ​__Subset Construction__ prezentat la curs) si minimizarea acestuia folosind, de asemenea, recomandat, algoritmul prezentat la curs.+Procedura de implementare a unui lexer pe care o vom urma la acest curs va fi una **bottom-up**. Astfel, **etapa ​1** a proiectului consta in conversia ​unui Automat Finit Nedeterminist (AFN) in Automat Finit Determinist (AFD) (folosind ​algoritmul ​__Subset Construction__ prezentat la curs) si minimizarea acestuia folosind, de asemenea, recomandat, algoritmul prezentat la curs.
  
-Tema va fi implementata in Python, iar scheletul va ofera un pattern ​pentru implementarea functionalitatilor necesare.+Tema va fi implementata in Python, iar scheletul va ofera un punct de plecare ​pentru implementarea functionalitatilor necesare.
  
 ====Structura scheletului==== ====Structura scheletului====
  
-In scheletul temei veti gasi 2 clase: **NFA** si **DFA**. In fiecare veti avea de implementate metodele necesare pentru verificarea comportamentului lor si pentru a realiza conversia ceruta de tema.+In scheletul temei veti gasi 2 clase: **NFA** si **DFA**. ​
  
 === Clasa DFA === === Clasa DFA ===
  
-Un DFA va fi descris de urmatoarele ​campuri:+Un AFD va fi descris de urmatoarele:​
 <​code>​ <​code>​
 S - alfabetul limbajului, reprezentat ca un set de string-uri S - alfabetul limbajului, reprezentat ca un set de string-uri
-K - starile ​automatului, ​reprezentat ​ca un set de __STATE__+K - multimea starilor ​automatului, ​reprezentata ​ca un set de __STATE__
 q0 - starea initiala a automatului q0 - starea initiala a automatului
-d - functia de tranzitie, reprezentata ca un dictionar ​cu cheie (stare, caracter_alfabet) ​si alta stare ca si valoare +d - functia de tranzitie, reprezentata ca un dictionar ​care asociaza unei perechi ​(stare, caracter_alfabet), o stare-succesor 
-F - starile ​finale ale automatului+F - multimea starilor ​finale ale automatului, reprezentata ca un set de __STATE__
 </​code>​ </​code>​
  
-Desi cea mai simpla modalitate de a ne referi la o stare este printr-un numar intreg, in anumite componente ale proiectului ​(si de la aceasta etapa, dar si de la etape viitoare) ​va fi mult mai convenabil sa lucram cu alte tipuri ​de etichete ​pentru stari (de exemplu, seturi de intregi sau tupluri). ​De aceea, parametrul ​''​STATE''​ va permite sa utilizati ce tip doriti ​ca si stare a automatuluiputeti nota starile automatului atat cu intregi ''​0,​1,​2,​3,​...'' ​cat si cu siruri de caractere ''​s0,​q1,​sink,​...''​ sau alte tipuri de date (''​frozenset''​)+Desi cea mai simpla modalitate de a ne referi la o stare este printr-un numar intreg, in anumite componente ale proiectului va fi mult mai convenabil sa lucram cu alte tipuri pentru ​identitatea unei stari (de exemplu, seturi de intregi sau tupluri). ​Parametrul ​''​STATE''​ va permite ​aceasta flexibilitate. In etapa 1, puteti ​sa utilizati ce tip doriti ​pentru reprezentarea unei starispre exemplu folosind ​intregi ''​0,​1,​2,​3,​...''​siruri de caractere ''​s0,​q1,​sink,​...''​ sau alte tipuri de date (''​frozenset''​)
  
-  - In aceasta clasa veti avea de implementat **obligatoriu** functia ''​accept'', ​functie ​care primeste un cuvant si ruland DFA-ul pe acel cuvant va intoarce ''​True''​ daca cuvantul este acceptat, iar ''​False''​ in caz contrar. +  - In aceasta clasa veti avea de implementat **obligatoriu** functia ''​accept'',​ care primeste un cuvant si simuland executia AFD-ului pe acel cuvant va intoarce ''​True''​ daca cuvantul este acceptat, iar ''​False''​ in caz contrar. 
-  - Functia ​''​minimize''​ este, de asemenea ​**obligatoriu** de implementatpentru obtinerea puntajului maxim, dar nu este absolut ​necesara pentru realizarea etapelor urmatoare. +  - functia ​''​minimize''​ este **obligatoriu** de implementat pentru obtinerea puntajului maxim, dar nu este necesara pentru realizarea etapelor urmatoare. 
-  - Functia ''​remap_states''​ **nu este** obligatoriu de implementat,​ din moment ce nu este apelata de checker, insa este recomandata ​din moment ce va va usura implementarea algoritmului subset construction. Ea are ca scop **transformarea** setului de stari, de la un tip (spre exemplu ​ //string//) la un altul (spre exemplu, //​integer//​). Astfel de transformari vor fi necesare, in special in etapele ulterioare ale proiectului.+  - Functia ''​remap_states''​ **nu este** obligatoriu de implementat,​ din moment ce nu este apelata de checker, insa este recomandata. Aceasta ​va simplifica ​implementarea algoritmului subset construction. Ea are ca scop **transformarea** setului de stari, de la un tip (spre exemplu ​set cu elemente de tip //string//) la un altul (spre exemplu, ​set cu elemente de tip //​integer//​). Astfel de transformari vor fi necesare, in special in etapele ulterioare ale proiectului.
  
 Spre exemplu, daca am avea automatul de mai jos: Spre exemplu, daca am avea automatul de mai jos:
Line 68: Line 69:
 */ */
  
-Am putea aplica functia ''​x -> '​q'​ + str(x+2)'',​ care ar creea un DFA cu urmatoarele stari:+Am putea aplica functia ''​x -> '​q'​ + str(x+2)'',​ care ar creea un AFD cu urmatoarele stari:
  
 {{:​lfa:​2023:​remap_after.png?​400|}} {{:​lfa:​2023:​remap_after.png?​400|}}
Line 82: Line 83:
 ===Clasa NFA=== ===Clasa NFA===
  
-Clasa functioneaza in aceeasi maniera cu cea a DFA-ului, cu o singura ​diferenta+Clasa functioneaza in aceeasi maniera cu cea a AFD-ului, cu o singura ​particularitate
-  * Spre deosebire de reprezentarea de la curs, unde $math[\Delta] ​reprezenta o relatie peste $math[K \times \Sigma \times K], in Etapa 1, ''​d'' ​va fi tot o functie, (codificata printr-un dictionar), ​care va asocia unei perechi (stare, caracter_alfabet),​ un **set de stari** succesor (in loc de o stare unica, asa cum se intampla intr-un DFA). +  * Relatia ​$math[\Delta] ​va fi reprezentata tot folosind un dictionar ​''​d''​ care va asocia unei perechi (stare, caracter_alfabet),​ un **set de stari** succesor (in loc de o stare unica, asa cum se intampla intr-un DFA). 
  
 Alte observatii: Alte observatii:
-  - Functia ''​epsilon_closure''​ primeste o stare a automatului si intoarce un set de stari, care reprezinta starile la care se poate ajunge doar prin epsilon-tranzitii de la starea initiala (fara a consuma nici-un caracter) +  - Functia ''​epsilon_closure''​ primeste o stare a automatului si intoarce un set de stari, care reprezinta starile la care se poate ajunge doar prin epsilon-tranzitii de la starea initiala (fara a consuma nici un caracter) 
-  - Functia ''​subset_construction''​ va intoarce un DFA, construit din NFA-ul curent prin algoritmul __subset construction__. ​DFA-ul intors va avea ca tip al starilor ''​frozenset[STATE]'' ​(starile ''​0''​ si ''​1''​ dintr-un NFA vor ajunge o multime de stari ''​{0,​1}''​ dintr-un DFA). Folosim ''​frozenset''​ in loc de ''​set'',​ pentru ca acesta din urma **nu este imutabil** (seturile pot fi modificate prin efecte laterale). Avem nevoie de un obiect **imutabil** pentru a putea calcula un hash (mereu acelasi), si implicit pentru a putea folosi astfel de obiecte drept chei intr-un dictionar (lucru imposibil daca obiectul-cheie este mutabil). +  - Functia ''​subset_construction''​ va intoarce un AFD, construit din AFN-ul curent prin algoritmul __subset construction__. ​AFD-ul intors va avea ca tip al starilor ''​frozenset[STATE]''​. Folosim ''​frozenset''​ in loc de ''​set'',​ pentru ca acesta din urma **nu este imutabil** (seturile pot fi modificate prin efecte laterale). Avem nevoie de un obiect **imutabil** pentru a putea calcula un hash (mereu acelasi), si implicit pentru a putea folosi astfel de obiecte drept chei intr-un dictionar (lucru imposibil daca obiectul-cheie este mutabil). 
-  - Functia ''​remap_states'' ​care are acelasi format si scop ca functia de la DFA-uri+  - Functia ''​remap_states''​ are acelasi format si scop ca functia de la AFD-uri
  
-Functiile ''​epsilon_closure''​ si ''​subset_construction''​ **sunt obligatoriu** de implementat, ​iar functia ''​remap_states''​ **nu** este.+Functiile ''​epsilon_closure''​ si ''​subset_construction''​ **sunt obligatoriu** de implementat, ​insa functia ''​remap_states''​ **nu** este 
 +.
  
 ===== Testare ===== ===== Testare =====
  
-Verificarea corectitudinii implementarii voastre se va face automat, printr-o serie de teste unitare, teste care vor verifica comportamentul fiecarei functii obligatorii de implementat,​ astfel se va verifica echivalenta intre DFA-urile create de ''​subset_construction''​ si ''​minimize''​ cu un DFA minim dat ca referinta.+Verificarea corectitudinii implementarii voastre se va face automat, printr-o serie de teste unitare. Testele ​vor verifica echivalenta intre AFD-urile create de operatiile ​''​subset_construction''​ si ''​minimize''​ cu un AFD minimal ​dat ca referinta.
  
-Un alt check preliminar care se va face pe fiecare DFA construit va fi unul care verifica ​integritatea ​lui d.p.d.v. structural (starea initiala si starile finale sunt incluse in multima de stari, nu are tranzitii definite pe un caracter dintr-o anume stare, are tranzitii definite pe fiecare pereche (stare, caracter)).+O alta verificare ​va urmari ​integritatea ​AFDului ​d.p.d.v. structural (starea initiala si starile finale sunt incluse in multima de stari, nu are tranzitii definite pe un caracter dintr-o anume stare, are tranzitii definite pe fiecare pereche (stare, caracter) 
 +).
  
 ==== Python ==== ==== Python ====
  
-Versiunea de python pe care o vom folosi pentru aceasta tema este ''​python3.12''​. Un ghid de instalare a acestei versiuni poate fi gasita ​[[https://​aruljohn.com/​blog/​install-python/​|aici]]+Versiunea de python pe care o vom folosi pentru aceasta tema este ''​python3.12''​. Un ghid de instalare a acestei versiuni poate fi gasit [[https://​aruljohn.com/​blog/​install-python/​|aici]]
  
 <note important>​ <note important>​
Line 110: Line 113:
  
 Pentru rularea testelor folositi comanda ''​python3.12 -m unittest''​. Pentru rularea testelor folositi comanda ''​python3.12 -m unittest''​.
-Aceasta comanda va detecta automat testele definite in folder-ul ''​test''​ si le va rula pe rand, afisand la final testele care au esuat, daca exista.+Aceasta comanda va detecta automat testele definite in folder-ul ''​test''​ si le va rula pe rand, afisand la final testele care au esuat, daca exista 
 +.
  
 ==== Structura arhivei ==== ==== Structura arhivei ====
  
-Veti incarca in assignment-ul de pe moodle o arhiva ''​zip''​ care va avea la baza folderul ''​src''​ din schelet+Veti incarca in assignment-ul de pe moodle o arhiva ''​zip''​ care va avea la baza folderul ''​src''​ din schelet ​si fisierul ''​ID.txt''​ ce contine user@stud.acs.pub.ro pe prima linie
 <​code>​ <​code>​
 . .
 └── src └── src
 +    ├── __init__.py
     ├── DFA.py     ├── DFA.py
     ├── NFA.py     ├── NFA.py
     ... (alte surse pe care le folositi)     ... (alte surse pe care le folositi)
 +├── ID.txt
 </​code>​ </​code>​