This is an old revision of the document!


Deadline etapa 1: 20 nov 2023 23:59

Schelet etapa 1 lfa_2023-skel-1.zip

Proiect

Proiectul consta in implementarea unui lexer in python.

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.

Care este input-ul unui lexer?

Lexer-ul primeste initial o specificatie de forma:

TOKEN1 : REGEX1;

TOKEN2 : REGEX2;

TOKEN3 : REGEX3;

...

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.

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.

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.

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)

Tema va fi implementata in Python, iar scheletul va ofera un pattern pentru implementarea functionalitatilor necesare.

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.

Clasa DFA

Un DFA va fi descris de urmatoarele campuri:

S - alfabetul limbajului, reprezentat ca un set de string-uri
K - starile automatului, reprezentat ca un set de __STATE__
q0 - starea initiala a automatului
d - functia de tranzitie, reprezentata ca un dictionar cu cheie (stare, caracter_alfabet) si alta stare ca si valoare
F - starile finale ale automatului

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 automatului, puteti 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)

  1. 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.
  2. 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.

Spre exemplu, daca am avea automatul de mai jos:

> (0) -a,b-> (1) ----a----> ((2))
               \-b-> (3) <-a,b-/
                   /     \
                   \-a,b-/

Am putea aplica functia x → 'q' + str(x+2), care ar creea un DFA cu urmatoarele stari:

> (q2) -a,b-> (q3) ----a----> ((q4))
                \-b-> (q5) <-a,b-/
                    /     \
                    \-a,b-/

Clasa NFA

Clasa functioneaza in aceeasi maniera cu cea a DFA-ului, cu o singura diferenta:

  • Spre deosebire de reprezentarea de la curs, unde $ \Delta$ reprezenta o relatie peste $ 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).

Alte observatii:

  1. 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)
  2. 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 in starea 01 dintr-un DFA) deoarece frozenset-ul este un obiect immutable, lucru care permite calcularea unui hash pentru aceste, sau mai pe scurt folosirea lui ca si cheie intr-un dictionar (lucru irealizabil cu un set obisnuit)
  3. Functia remap_states care are acelasi format si scop ca functia de la DFA-uri

Functiile epsilon_closure si subset_construction sunt obligatoriu de implementat, iar functia remap_states nu este.

Verificarea corectitudinii implementarii voastre se va face automat, printr-o serie de teste unitare, teste care vor verifica comportamentul fiecarei functii obligatorii de implementat si ii va testa output-ul pe o diversitate de input-uri.

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).

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 aici

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.

Structura arhivei

Veti incarca in assignment-ul de pe moodle o arhiva zip care va avea la baza folderul src din schelet

.
└── src
    ├── DFA.py
    ├── __init__.py
    ├── NFA.py
    ... (alte surse pe care le folositi)