Un’espressione regolare rappresenta in maniera finita un linguaggio, ossia un insieme potenzialmente infinito di sequenze di simboli tratto da un alfabeto Sigma.
In generale, se <re1>, <re2> ... <rek> sono delle regexp, lo saranno anche
<re1><re2>...<rek>(sequenza)<re1>|<re2>(or)<re1>*(chiusura di Kleene)<re1>+(ripetizione 1 o più volte)
Ad ogni regexp corrisponde un automa a stati finiti non-deterministico (o NFA) in grado di determinare se una sequenza di “simboli” appartiene o no all’insieme definito dall’espressione regolare, in un tempo asintoticamente lineare rispetto alla lunghezza della stringa.
In particolare, in Lisp, le espressioni regolari saranno espresse come:
<re1><re2>...<rek>diventa(seq re1 re2 ... rek)<re1>|<re2>diventa(or re1 re2 ... rek)<re1>*diventa(star re1)<re1>+diventa(plus re1)
L’alfabeto dei “simboli” Sigma è costituito da S-exps Lisp.
nfa.lisp permette di effettuare la compilazione di espressioni regolari in automi non deterministici secondo l'algoritmo di Thompson. E' composta da tre funzioni principali:
is-regexp (RE): verifica che l'input sia un'espressione regolare.nfa-regexp-comp (RE): compila l'espressione regolare in un automa (differente in base al caso).nfa-test (FA input): verifica che l'espressione regolare passata sia riconosciuta dall'automa, ossia che consumandola completamente l'automa si trovi in uno stato finale.
-
is-regexp (RE)Funzione che serve per verificare se l'input sia o meno un'espressione regolare; innazitutto si considerano i due casi base, ossia:- epsilon è un'espressione regolare
- un simbolo atomico è un'espressione regolare.
In questi due casi viene ritornato T. Il caso ricorsivo si verifica quando l'input è una lista, in tale evenienza viene chiamata la funzione d'appoggio
is-regexp-op.is-regexp-op (L)La funzione riconosce l' "operatore" in questione, prendendo in considerazione ilcardella lista. In particolare, per plus e star si è prestata attenzione al fatto che l'espressione regolare fosse composta da un solo elemento.
-
nfa-regexp-comp (RE)Per prima cosa si verifica nuovamente che l'input sia una un'espressione regolare, in caso positivo si ricontrolla ilcardiREper identificare l'operatore in questione e chiamare di conseguenza la funzione atta alla generazione dell'automa ad esso corrispondente, sempre secondo l'algoritmo di Thompson.(setf state-number -1)Si è impostata la variabile che indica il numero dello stato corrente(state-number)a -1, dal momento che viene utlizzata la funzioneincrement-state-numberper creare i nuovi stati dal nome univoco (partendo da 0).atom-nfa-create (RE)Genera l'NFA corrispondente a una regexp atomica, creando una lista contenente:- stato iniziale
- stato finale
- la delta, che è ovviamente una sola ed è composta dallo stato iniziale, dall'espressione regolare atomica stessa (come input da consumare per cambiare stato) e dallo stato finale.
sexp-nfa-create (sexp)Funziona in maniera analoga alla funzioneatom-nfa-create; ma la delta ha come input da consumare la lista stessa (sexp), ossia un'espressione regolare senza ilcarriservato (seq, or, plus, ...).seq-nfa-create (nfa-list)&seq-temp (final-nfa list-of-nfa)Costruisce l'NFA corrispondente ad una sequenza di espressioni regolari (<RE1><RE2>...<REn>)facendo uso di una funzione d'appoggionfa-merge (first-nfa second-nfa)che con due espressioni regolari genera due NFA e successivamente li unisce in un unico NFA.or-nfa-create (nfa-list)Generazione dell'NFA per le regexp inor (<RE1>|<RE2>|...|<REn>).or-nfa-transitions (nfa-list)Funzione che crea una lista delle delta per le regexp in or.
plus-nfa-create (nfa)Creazione dell'NFA corrispondente aplus (<RE>+), ossia una ripetizione (1 o più volte).star-nfa-create (nfa)Costruzione dell'NFA corrispondente astar (<RE>*), ovvero alla chiusura di Kleene (ripetizione 0 o più volte).nfa-create (initial-state final-state delta)Crea una lista di stati iniziali, una di stati finali e aggiunge ogni delta ad una lista di delta.nfa-initial-state (nfa)Ritorna lo stato iniziale dell'automa in input.increment-state-number ()E' un semplice incremento (per poter iniziare con lo stato iniziale = 0).nfa-final-state (nfa)Ritorna lo stato finale dell'automa in input.get-transitions (nfa)Ottiene e ritorna la lista delle transizioni dell'NFA passato come input.contains-final-state (nfa state-list)Ritorna true se almeno uno stato tra quelli passati in input è finale.state-is-final (nfa state)Controlla se lo stato passato come input è finale, in tal caso ritorna T.- *
reset-all-nfas ()Funzione che fa ripartire da -1 (permettendo di stampare di nuovo da 0) i valori degli stati degli NFA già definiti, rendendoli sovrascrivibili. *Se la si vuole usare, va chiamata dal listener. initial-e-transitions (state nfa-list)&final-e-transitions (state nfa-list)Crea una lista delle epsilon-transizioni dallo stato corrente (input) verso lo stato iniziale/finale degli automi compilati.
-
nfa-test (FA input)Dato un input e un NFA restituisce:- T se l'NFA, consumando l'input, si trova poi in uno stato finale.
- NIL altrimenti
Si è anche aggiunto un controllo per verificare che l'input
FArispetti la struttura di un automa, in caso contrario stampa un messaggio d'errore.nfa-matrixFunzione d'appoggio anfa-testche "simula" l'esecuzione dell'NFA passato come input.list-of-eclosure-states (nfa closure states)Funzione che effettua le e-closures, ossia produce un insieme degli stati raggiungibili da un certo stato q tramite le epsilon-transizioni, degli stati in input restituendole come lista.transition-finder (transitions state input)Cerca e trova tutte le possibili transizioni di uno stato q (stato corrente) consumando un simbolo in input.list-of-next-states (nfa input-state input-sym)&list-of-nfa-states (nfa states input)Entrambe le funzioni servono a ritornare una lista degli stati successivi allo stato corrente dopo aver consumato un simbolo in input.