I 3 dizionari di NVDA.

Di Adriano Barbieri.

Terza parte.

`*********`

Adesso che abbiamo anche compreso cosa sono i gruppi tra parentesi tonde e come sfruttarne la loro potenzialit, per crearci il nostro "asterisco" personalizzato, in questo articolo prover ad elencare alcuni metodi per matchiare e manipolare la vocalizzazione di alcuni tipi di vocaboli.

Inoltre, prover a descrivere alcune tecniche utili che consentono di invertire, filtrare, e non far vocalizzare parti di una parola e anche, quando possibile, costruire un'espressione regolare che da sola  in grado di matchare anche alcune eventuali varianti di un vocabolo.

La peculiarit delle Regex, al pari di tutti i linguaggi di programmazione,come gi detto nella seconda parte di questa serie di articoli,  consentire di memorizzare parti di una stringa di matching, dandoci poi la possibilit di richiamarne il valore memorizzato semplicemente riferendoci al numero logico assegnato al gruppo.

Vi ricordo che il numero logico assegnato a un gruppo  un valore rappresentato dai numeri "1, 2, 3", eccetera, abbinato ad ogni gruppo rappresentato dalla coppia di parentesi tonde"()" aperta e chiusa, , da sinistra verso destra: Tenete presente che occorre contare anche i gruppi che potrebbero essere stati nidificati all'interno di un altro gruppo, perch anch'essi hanno un loro numero logico abbinato.

E' possibile quindi richiamare e far vocalizzare il contenuto del matching dei gruppi presenti nella nostra espressione regolare, ma non c' una regola che imponga il richiamo in un ordine definito, ci vuol dire che possiamo farlo nell'ordine a nostra scelta, ad esempio:

- Sempre dal dizionario temporaneo, facciamo invio su aggiungi.

- Nel primo campo digitiamo: "(N)(V)(D)(A)", come sempre senza le virgolette. Fate attenzione alle parentesi tonde.

- I 4 gruppi della Regex memorizzeranno ognuno la lettera assegnatagli.
Provate ora a richiamare i gruppi inserendo nel campo in sostituzione il numero logico precedendolo dalla barra diagonale rovesciata, cos: "\1 \2 \3 \4", notare che lo spazio tra un richiamo e l'altro non  obbligatorio,  stato inserito solo per generare uno "spelling", altrimenti la parola verrebbe letta tutta di un fiato. 
Questo anche a dimostrare che  possibile l'inserimento di caratteri o intere parole, nonch punteggiature e/o spaziatura fra i vari richiami.

Se avete una versione di NVDA recente, in cui il modulo dizionario  munito di due caselle di controllo in aggiunta, mi raccomando di marcare la casella di controllo della espressione regolare.

Cos facendo se scriverete: "NVDA" da blocco note e farete vocalizzare la riga digitata, non si avvertir nulla di strano, ma provate a mescolare l'ordine dei numeri logici presenti nel campo sostituzione e provate a far vocalizzare la riga precedentemente editata e vedrete che avrete una lettura molto diversa.

Perch funzioni, ovviamente serve che il matching sia true, cio vero, quindi  neccessario che il testo editato nel blocco note corrisponda appieno a ci che  stato previsto nel campo di ricerca, sia per quanto riguarda l'ordine, sia per quanto riguarda tipo e numero dei caratteri. Ulteriori combinazioni di caratteri digitati manterranno il loro stato originale e non verranno invertite, e verranno lette cos come sono state digitate.

Nulla ci impedisce a questo punto, di sfruttare i gruppi alla stregua di filtri. Potremmo far s che venga vocalizzata solo una parte del matching, scartando ci che non serve, provate ad esempio a togliere il richiamo di uno o due gruppi dal campo sostituzione, oppure ripetete alcuni richiami, la lettera o la parola memorizzata nei gruppi corrispondenti verr ripetuta per ogni richiamo abbinato al gruppo.

Fate poi vocalizzare la riga precedentemente digitata nel blocco note e noterete le differenze.

Con un poco di fantasia,  possibile immaginare che il sistema ci permetta di invertire e/o filtrare e/o far ripetere intere parole e/o parti di esse.

Vediamo adesso alcuni metodi per matchare una parola ambigua, per il semplice fatto che la stessa parola, a seconda del contesto cambia la posizione dell'accento, nella lingua italiana ce n un'infinit, eccone un piccolo esempio:

- "Desidri, desderi".

- "Rtina, retna".
- "Prtali, prtali".
- "Tndine, tendne.

Un particolare che ci consente di identificare il contesto, anche se a volte incorrono eccezioni,  l'articolo oppure  l'aggettivo che precede la parola, in altri casi la congiunzione che la segue, oppure la parola adiacente.

Innanzitutto occorre capire la nostra sintesi vocale cosa fa gi da sola, perch molte sintesi vocali hanno nel proprio "motore" degli algoritmi dedicati a interpretare nel modo migliore quelle parole ambigue. Per, siccome molto spesso non ci soddisfano i risultati, perch non  possibile prevedere tutto, accade che qualche cosa viene tralasciata per non perdere tempo oppure si opta per una via di mezzo, quindi, dobbiamo per forza intervenire.

Ecco qualche esempio:

- "Mi fa male il tendine".

- "Le tendine erano azzurrine".

Prendiamo ad esempio questa ultima parola, riferita al tendine di Achille... quello che arriva fino al tallone.... "Tendine", pu essere anche al plurale: "Tendini" e quindi bisogner tenerlo presente.

la nostra Regex dovr riconoscere dall'articolo se si tratta del tndine o di tendne. Quindi, potremmo creare un gruppo di controllo da anteporre al gruppo con la parola da matchare in oggetto, contenente una lista degli articoli determinativi ammessi, baster matchare l'ultima lettera pi uno spazio che dovrebbe essere parte dell possibile articolo che precede la parola "Tendin", un altro gruppo di controllo invece, si occuper di matchare l'ultima vocale della parola, per determinare se essa sar singolare o plurale, una cosa come questa ad esempio:

``# Tendine/i``.

``"([iIlL]\W)(TENDIN|[tT]endin)([eEiI]\W)	\1tndin\3	1	1"``.

Un sistema un po' blando, ma che permette di vocalizzare correttamente:

- "al tendine".

- "col tendine".

- "dal tendine".

- "del tendine".

- "nel tendine".

- "sul tendine".

Ma anche:

- "ai tendini"

- "dai tendini"

- "dei tendini"

- "coi tendini"

- "nei tendini"

- "sui tendini"

Insomma qualsiasi parola, che termini con uno dei caratteri racchiusi nella classe fra parentesi quadre contenuta nel primo gruppo dell'espressione regolare. Da notare anche che questi caratteri devono avere un carattere separatore prima del secondo gruppo, ed  indicato dal carattere speciale: ``"\W"`` (barra diagonale rovesciata doppia vu maiuscola), ma anche un ``"\s"`` (barra diagonale rovesciata s minuscola) andrebbe bene, questa indica uno spazio.

La Regex per accetter anche una frase del genere: "Questi tendini mi fanno male".

Ma non questa: "Questo tendine mi fa male".

Sar necessario aggiungere nella classe del primo gruppo la vocale finale, minuscola e maiuscola "oO", dell'aggettivo dimostrativo perch venga matchata correttamente.

Questo sistema  funzionale nella sua semplicit, ma lascia passare parole, qualsiasi parola che termini con una delle vocali ammesse nella classe, anche se insensate come:

- "fdghfi tendini".

- "dsfhfl tendine".

Per affinare la nostra Regex occorrerebbe aggiungere un ulteriore gruppo a sinistra, che consenta il matching solo se la frase  a inizio riga o preceduta da un carattere separatore come uno spazio, una tabulazione, una punteggiatura, eccetera.

Io normalmente uso questo gruppo: ``"(\W|^)"``.

Se questo gruppo lo mettiamo all'inizio di una Regex, esso, nella maggior parte dei casi, impedisce che vi siano caratteri appiccicati sulla immediata sinistra della frase da matchare. Se il gruppo poi lo si fa seguire da un'altro che contenga i nostri articoli o /e aggettivi, non saranno ammesse confusioni di sorta.

La Regex allora potrebbe esser cos: ``"(\W|^)(([iI]|[aAiIuU][iIlLnN]|[dDcCnNsS][aAeEoOuU][iIlL])\s)(TENDIN|[tT]endin)([eEiI]\W)	\1\2tndin\5	1	1"``.

Se fate caso alle classi contenute nel secondo gruppo, ci sono gli articoli determinativi ammessi, sia in minuscolo, sia in maiuscolo: "i, al, il, un, dal, del, col, nel, nei, sul".

L'ultimo gruppo, in entrambi gli esempi, si occupa di far terminare la nostra parola "Tendin" con la sola vocale che determiner se sar singolare o plurale.

Ovviamente se la nostra parola dovesse essere priva di articolo alla sua sinistra, il matching della Regex sar false e non verr eseguita.

Notare che, per limitare la lunghezza della riga, non ho inserito il controllo sugli aggettivi dimostrativi "questi e questo", ma una seconda Regex come questa risolverebbe il problema:

``# Tendine/i /questi/o``.

``"(\W|^)([qQ][uU][eE][sS][tT][iIoO]\W)(TENDIN|[tT]endin)([eEiI]\W)	\1\2tendin\4	1	1"``.

Le classi fra parentesi quadre permettono il matching di un solo carattere contenuto al loro interno, ma se una classe  affiancata da un altra classe, il carattere si somma al successivo formando la parola come se fosse cos: ``"[qQ]+[uU]+[eE]+[sS]+[tT]+[iIoO]"``.

Il matching fra multiple combinazioni di classi multiple ha termine appena viene raggiunto il carattere ``"|"`` (linea verticale che significa or), il quale determina una alternativa e di conseguenza un'altra serie di combinazioni di classi ammesse nel matching.

Infatti, alcuni articoli determinativi sono di un carattere, altri composti da due, e altri da tre caratteri, il tutto  poi raggruppato fra parentesi tonde nidificate solo perch tutte le classi devono avere uno spazio separatore: ``(articolo+spazio+parola)``.

Raggruppandole fra parentesi ho specificato che tutte sono soggette all'aggiunta di un separatore come ``"\W"``, o ``"\s"``, cos  stato sufficiente indicare il separatore una sola volta per tutte quante, altrimenti sarebbe stato neccessario, alla fine di ogni combinazione di classi, quindi prima di ogni ``"|"`` (barra verticale or), inserire il carattere speciale ``"\s"`` (barra diagonale rovesciata s minuscola).

Vediamo ora un altro metodo di matching che sfrutta il carattere speciale ``"."`` (punto fermo), indicante che  accettabile un carattere ignoto. E se volessimo un numero definito di caratteri ignoti? Ecco un esempio anche se parziale:

La parola "Fracassare", quante varianti ha?

- "Fracassarmela".

- "Fracassarmele".

- "Fracassarmeli".

- "Fracassarmelo"...

Qu ce la caveremo con questa Regex:

``# Fracassarmela/e/i/o``.

``"(FRACASSARMEL|[fF]racassarmel)([aAeEiIoO]\W)	Fracassrmel\2	1	1"``.

Funzionerebbe anche cos:

``# Fracassarmela/e/i/o``.

``"(FRACASSARMEL|[fF]racassarmel)(.\W)	Fracassrmel\2	1	1"``.

Abbiamo sostituito l'intera classe dell'ultimo gruppo con un singolo ``"."`` (punto fermo). In pratica, nel caso sopracitato ci serve un solo carattere per l'identificazione della parola, la vocale finale della parola stessa, e si sa che sono solo quattro in tutto, anche se il solo punto fermo lascer passare altri caratteri oltre alle sole vocali richieste, ma pu andar bene ugualmente, dipende da quanto si vuol essere pignoli.

Ma se fosse invece:

- "Fracassartela"

- "Fracassartele"

- "Fracassarteli"

- "Fracassartelo"

Be'! un'altra regex in supporto come questa andrebbe bene:

``"(FRACASSARTEL|[fF]racassartel)(.\W)	Fracassrtel\2	1	1"``.

E siamo a 2 Regex!ma se fosse:

- "Fracassargliela"

- "Fracassarmelo"

- "fracassarsele"

- "fracassarglieli"

In questo particolare caso, considerando che la parola "Fracassar" e ricorsiva in quasi tutte le varianti, possiamo risolvere la questione con una sola Regex che preveda un numero variabile di caratteri ignoti, e ci vengono in soccorso le parentesi graffe.

Esse, come detto nel precedente articolo, ci permetttono di definire un limite minimo e massimo di rippetizioni dell'ultimo carattere che le precede, anche se si tratta di un carattere speciale, il punto fermo, come nel nostro caso, ed ecco cosa otteniamo:

``# Fracassargliela/mela/sela/tela/e/i/o``.

``"(FRACASSAR|[fF]racassar)(.{4,6}\W)	Fracassr\2	1	1"``.

La riga di commento dopo il carattere ``"#"`` elenca tutto ci che la regex dovrebbe accettare in grandi linee, quindi, se il matching della parola: "fracassar", sar true, saranno ammessi in aggiunta un minimo di quattro caratteri fino ad un massimo di sei caratteri ignoti, appiccicati alla parola "fracassar".

Purtroppo per, anche "fracassardxdghf" sar accettata, ma contiamo che nessuno user mai una parola cos palesemente errata, sicuri di non sbagliare.

Ecco un'altro esempio:

``# Precluderla/e/i/o/gli``.

``"(PRECLUDER|[pP]recluder)(.{2,3}\W)	Preclder\2	1	1"``.

Vediamo un altro metodo che sfrutta ancora le classi, ossia un gruppo di caratteri o numeri racchiusi fra parentesi quadre.

Ne abbiamo gi parlato, e abbiamo visto che per ogni classe  preso in considerazione solo un carattere alla volta tra quelli presenti nella lista per ogni classe, e sottolineo per ogni classe.

Questo significa che, affiancare delle classi tra di loro, ci consente di formare delle parole intere, esattamente come se ad esempio scrivessimo: "nvda", o ``"[n][v][d][a]"``, con il vantaggio per, che le classi ci consentono di inserire delle varianti, tramite l'aggiunta di altri caratteri all'interno di ogniuna,creando delle liste ad esempio cos:

``"[nN][vV][dD][aA]"``.

In questo modo abbiamo detto che la parola "nvda"  ammessa sia in minuscolo e anche in maiuscolo.

Comodo per matchare parole un po' pi lunghe come ad esempio questa:

``# Grondano/ino``.

``"(GROND|[gG]rond)([aAiI][nN][oO]\W)	Grnd\2	1	1"``.

Come potete vedere, la Regex appena descritta consente di matchare:

- "Grondano"

- "Grondino"

Oppure quest'altra un po' pi complessa, ma sempre sfruttante lo stesso principio delle classi affiancate:

``# Grassocce/i/ia/io``.

``"(GRASSOCC|[gG]rassocc)([eEiI]\W|([iI][aAoO])\W)	Grasscc\2	1	1"``.

Questa Regex consente di matchare:

- "Grassocce"

- "Grassocci"

- "Grassoccia"

- "Grassoccio"

Un ultimo esempio:

``# Tingerci/mi/ne/si/ti/vi/gli``.

``"(TINGER|[tT]inger)([cCmMnNsStTvV][eEiI]|[gG][lL][iI]\W)	Tnger\2	1	1"``.

Questa Regex consente di matchare:


- "Tingerci"

- "Tingermi"

- "Tingerne"

- "Tingersi"

- "Tingerti"

- "Tingervi"

- "Tingergli"

Dalla stesura del primo articolo dedicato ai dizionari di Nvda  passato un po' di tempo, in quel periodo non ero ancora molto pratico a gestire le punteggiature per matchare le famose emoticons, le faccine che spesso vengono usate nei messaggi di posta elettronica o nelle sezioni di chat.

Confesso che crearle mi fece perdere parecchio tempo e arrivai a dichiarare che a causa dell'ambiguit con l'uso di caratteri speciali usati nelle Regex la cosa era stata molto difficoltosa, ma ora mi sono ricreduto. Infatti, combinando la tecnica delle classi affiancate e con l'uso delle parentesi graffe la cosa  semplicissima.

Occorre solo mettere le cose nel giusto ordine, aggiungendo,se necessario, delle classi se l'emoticon dovesse essere composta da pi di due o tre caratteri, come invece prevede l'esempio che segue.

Ecco come ho creato la faccina...
``# :)) Emoticon Faccina che ride di gusto``.

``"(\s|^)(\:([-][)]{2,}|[)]{2,}))(\s|\W)	\1Faccina che ride di gusto\4	1	1"``.

Il primo gruppo si occupa di verificare che la faccina abbia uno (spazio), indicato dal carattere speciale: "\s" (barra diagonale rovesciata s minuscola), oppure che la nostra faccina sia ad inizio riga, indicato dall apice "'" (accento circonflesso).

Il secondo gruppo contiene le classi che compongono la faccina vera e propria. Si pu notare il carattere ``":"`` (due punti) per gli occhietti,che  preceduto dalla ``"\"`` (barra diagonale rovesciata) ad indicare che i due punti devono essere trattati alla stregua di semplice carattere e non come carattere speciale, seguito da una classe contenente il ``"-"`` (trattino), il nasino, segue un'altra classe che contiene la ``")"`` (parentesi chiusa), il ghigno sorridente della nostra emoticon.

Subito seguita da un gruppo di parentesi graffe, ad indicare le ripetizioni ammesse del carattere che le precedono; in questo caso la parentesi chiusa del sorriso  ammessa da un minimo di due ripetizioni fino a fine riga perch non  stato indicato il limite massimo dopo la (virgola).

Segue l'alternativa, ossia la stessa faccina, ma senza il nasino questa volta.

Le due alternative  sono state raggruppate fra parentesi tonde senza gli occhietti... I due punti che li raffigurano sono stati inseriti una sola volta subito prima delle due alternative, cio appena all'inizio e subito all'interno del secondo gruppo di parentesi tonde.
Ovviamente se si intende sostituire gli occhietti raffigurati dai ``":"`` (due punti) con, ad esempio, il ``";"`` (punto e virgola) per indicare la strizzatina d'occhio, non essendo un carattere che possa essere confuso come un carattere speciale, sar possibile usarlo senza anteporvi la ``"\"`` (barra diagonale rovesciata).

Infine, l'ultimo gruppo di chiusura della Regex controlla che non vi sia appiccicato nient'altro, tranne un eventuale spazio.

Per non generare confusioni con un'altra Regex simile che intercetta la faccina sorridente, cio quella composta da una sola parentesi tonda chiusa,  necessario metterla dopo di quella appena descritta.

Questo per dire che le Regex, in alcune eccezioni non devono essere sempre accodate una all'altra indiscriminatamente; s,  giusto mantenere per quanto possibile un ordine alfabetico inanzitutto, ma a volte per evitare conflitti di matching  neccessario dare la precedenza alle Regex che elaborano cose molto somiglianti fra loro, questo perch i dizionari di Nvda vengono letti e memorizzati dal modulo,l'ho gi detto e lo ribadisco, sempre in cascata, dall'alto verso il basso.

Per eventuali chiarimenti, scrivere a: `Adriano Barbieri. <barbadriano@libero.it>`_

