....la continuazione
Regola 7
Le parentesi quadre sono metacaratteri, vengono usate per indicare delle alternative a carattere singolo oppure delle alternative composte da una serie di caratteri (è possibile fare un misto) il tutto è detto classe di caratteri
esempio:
“/a[bcdef]/” equivale ad “/a(b|c|d|e|f)/”
“/a[b-f]/” è come l’esempio sopra (indica da ‘b’ ad ‘f’)
“/[A-Za-z]/” indica qualsiasi carattere maiuscolo o minuscolo (da ‘A’ a ‘Z’ oppure da ‘a’ a ‘z’).
Se come primo carattere tra le parentesi quadre appare un ‘^’ la classe di caratteri viene negata.
“/a[^bc]/” una “a” seguita da qualsiasi carattere che non sia una “b” o una “c”.
La classe di caratteri può contenere soltanto atomi.
Regola 8
Quando l’engine ha una preg con varie alternative, prova a riscontrarle una ad una, quando un’alternativa fallisce l’engine torna indietro e prova la seconda, se fallisce torna indietro e prova la terza e così via. Questo ‘tornare indietro e provare l’alternativa successiva’ viene fatto seguendo delle regole ben precise ed è detto: backtracking.
Per comprendere il backtraching bisogna, prima di tutto, aver ben chiare le regole di cui sopra, e considerarle come delle funzioni che si richiamano a vicenda l’una con l’altra, ogni funzione restituisce il peso in caratteri (un semplicissimo numero intero) oppure false a secondo che il confronto abbia avuto successo oppure no; il chiamante valuta questo valore: se il valore è un peso continua altrimenti prova un’altra alternativa se non ci sono + alternative termina restituendo false al suo chiamante.
Vediamo subito come funziona.
Nell’esempio che segue sono coinvolte alcune delle regole che sopra ho descritto quindi immaginiamo di avere le seguenti funzioni che li racchiudono:
regola1(); // l’engine scorre la preg da sinistra a destra
regola2(); // l’engine scorre la stringa da sinistra a destra
regola3(); // atomi e asserzioni
regola5(); // quatificatori
abbiamo una stringa “baxyde”
ed una preg “/ax{1,2}y{1,2}/”
analizziamo come si composta l’engine:
Passo 1
Si parte con regola2(); il puntatore viene posizionato prima del primo carattere della stringa, per cui (indicando con un punto ‘.’ Il puntatore) avremo “.baxyde”;
Passo 2
regola2() richiama regola1(); secondo la quale l’engine valuta la preg da sinistra a destra
Passo 3
regola1() richiama regola3() perché il primo carattere della preg è un atomo; per cui l’engine dovrà riscontrare l’atomo ‘a’ nella posizione corrente del puntatore stringa ma il confronto fallisce e l’engine fa backtracking ritornando alla regola chiamante cioè regola1() e gli restituisce false indicando appunto il fallimento.
Passo 4
Siamo tornati a regola1() che valutando il risultato ottenuto al passo precedente termina anch’essa restituendo false al suo chiamante
Passo 5
Siamo in regola2() il valore restituito dal passo 4 è false per cui tenta un’altra alternativa: il puntatore viene spostato un passo avanti ed avremo quindi “b.axyde” (il punto ’.’ è sempre il puntatore)
Passo 5 come passo 2
Passo 6
Simile al passo 3: regola1() richiama regola3() ma questa volta il riscontro c’è, ed ha un peso in caratteri pari ad 1 (perché è stato riscontato un atomo) per cui regala3() restituisce il peso al chiamante indicando il successo.
Passo 7
Siamo tornati a regola1() il valore restituito dal passo precedente è un peso per cui un successo, si procede quindi a scorrendo la preg di ed incontriamo l’atomo ‘x’ con il quantificatore ‘{1,2}’, tale confronto verrà effetuato sulla nostra stringa non nella posizione attuale ma nella posizione attuale + 1 perché il passo 6 ha indicato che il peso del riscontro è pari ad 1 carattere.
Passo 8
regola1() richiama regola5() secondo la quale viene fatto un confronto ingordo, per cui l’engine tenta “xx” che fallisce.
Passo 9
siamo ancora in regola5() il passo precedente è fallito ma, prima di decretare il fallimento della funzione dobbiamo verificare le eventuali alternative: il modificatore era ‘{1,2}’ quindi, adesso, tentiamo un riscontro con ‘x’ ed abbiamo successo; Per cui regola5() termina restituendo il peso del riscontro che è 1;
Passo 10
siamo tornati a regola1() ed il passo precedente ha restituito peso uno, la funzione prosegue nel valutare la preg ed incontra ‘y{1,2}’ tale confronto (come al passo7) dovrà essere effettuato sulla nostra stringa nella posizione attuale + 2 (uno del passo 6 + uno del passo 9)
Passo 11 come passo 8 ma con ‘yy’
Passo 12 come passo 9 ma con ‘y’
Passo 13
siamo di nuovo a regola1() la preg è terminata per cui la funzione termina restituendo peso 3 (il totale) al chiamante
Passo 14
siamo in regola 2 il passo precedente ha restituito un peso per cui la preg è integralmente soddisfatta. Il puntatore di scorrimento era “b.axyde”, abbiamo un peso di 3 per cui l’engine termina restituendo “axy”;
Questo è tutto! Ciao a tutti