
Che cos'è un analizzatore (parser)?
- VersionDude
- Parsing
- 5 min di lettura
Un analizzatore trasforma un flusso di caratteri in dati strutturati utilizzabili da un programma — il passo tra il testo grezzo e il significato.
Un analizzatore (parser) è il componente che legge un testo in ingresso e ne costruisce una rappresentazione strutturata con cui un programma può realmente lavorare. Il testo grezzo è solo una sequenza di caratteri senza significato intrinseco per il software; l'analizzatore è il passo che trasforma quel flusso piatto in qualcosa dotato di forma e gerarchia. Si colloca al confine tra il testo scritto da un umano o generato da una macchina e i dati strutturati di cui il resto di un programma ha bisogno.
Due fasi: tokenizzare, poi costruire un albero

La maggior parte degli analizzatori funziona in due passi distinti. Il primo passo, un tokenizzatore o lexer, raggruppa i caratteri in unità significative — tag, parole, numeri, operatori, simboli — così che l'ingresso non sia più caratteri individuali ma una sequenza di token. Il secondo passo, la costruzione dell'albero, dispone questi token in una gerarchia secondo una grammatica, producendo un albero strutturato. Separare questi due compiti mantiene ciascuno più semplice, ed è uno schema che rivedrai ancora e ancora.
La tokenizzazione da sola risolve molta ambiguità. Considera come i caratteri che formano un tag di apertura, un nome di attributo e un valore tra virgolette debbano essere riconosciuti come cose distinte prima che qualsiasi struttura possa essere costruita; il tokenizzatore è ciò che stabilisce queste distinzioni. È solo una volta che l'ingresso è un flusso pulito di token che il passo di costruzione dell'albero può ragionare su come si annidano e si relazionano gli uni agli altri.
Gli analizzatori sono ovunque
Gli analizzatori sono veramente ovunque non appena si comincia a guardare. I compilatori analizzano il codice sorgente in un albero sintattico astratto prima di generare istruzioni macchina; i browser analizzano l'HTML e il CSS per costruire le strutture che renderizzano; e le applicazioni ordinarie analizzano JSON, XML, YAML e file di configurazione a ogni avvio. Quasi ogni programma che accetta del testo in ingresso ha un analizzatore da qualche parte al suo interno, anche se l'autore non lo pensa mai con questo nome.
Perché l'uscita è un albero
L'uscita di un analizzatore è generalmente un albero, e il tipo di albero dipende dal dominio. Per un linguaggio di programmazione, è un albero sintattico astratto che cattura la struttura delle espressioni e delle istruzioni; per una pagina web, è il DOM, l'albero di elementi e nodi di testo che il browser costruisce a partire dall'HTML. In entrambi i casi, è l'albero, e non il testo originale, su cui operano i passi successivi.
Il motivo per cui un albero è l'uscita naturale è che la maggior parte dei linguaggi e dei formati di documento è intrinsecamente annidata. Un'espressione contiene sotto-espressioni, un elemento contiene elementi figli, un blocco di configurazione contiene blocchi annidati. Un elenco piatto di token non può catturare questo annidamento, ma un albero lo esprime direttamente, il che spiega perché l'analisi è così spesso descritta come la trasformazione di un flusso unidimensionale in una struttura a più livelli.
Cosa rende insolita l'analisi dell'HTML
Ciò che rende l'analisi dell'HTML insolita tra tutti questi esempi è il suo recupero degli errori standardizzato. Il markup del mondo reale è pieno di errori — tag non chiusi, elementi mal collocati, attributi in posizioni strane — eppure le pagine devono comunque visualizzarsi. La specifica HTML risponde a questo definendo esattamente come un analizzatore debba trattare ogni tipo di ingresso malformato, anziché lasciare che ogni implementazione indovini.
La conseguenza di questa specifica precisa è un'interoperabilità notevole. Poiché le regole di recupero degli errori sono dettagliate nel menu, ogni browser moderno costruisce lo stesso albero DOM a partire dallo stesso ingresso rotto, anziché che ciascuno improvvisi diversamente. È per questo che una pagina malformata si visualizza in modo coerente tra browser, e ciò contrasta con formati più rigorosi come XML, che rifiutano semplicemente un ingresso non ben formato anziché tentare di ripararlo.
Tollerante contro rigoroso, per progettazione
Questo contrasto mette in luce un compromesso di progettazione deliberato. Un analizzatore indulgente come quello dell'HTML privilegia la resilienza e il fatto che l'utente veda sempre qualcosa, al prezzo di lasciar passare in silenzio gli errori. Un analizzatore rigoroso come quello dell'XML privilegia la correttezza e la prevedibilità, al prezzo di rifiutare in partenza un ingresso imperfetto. Nessuno è universalmente migliore; ciascuno si addice al compito per cui è stato concepito, e riconoscere quale filosofia segue un formato ti dice molto sul suo comportamento.
Un modello mentale per tutto lo stack
Non appena si comincia a vedere il software come una serie di analizzatori che trasformano il testo in struttura, gran parte dello stack web diventa più facile da ragionare. Il browser che analizza l'HTML in DOM, il motore che analizza il JavaScript in un albero sintattico, il server che analizza un corpo di richiesta JSON — sono tutte la stessa idea applicata in luoghi diversi. Questo unico prisma, del testo che diventa dati strutturati tramite un analizzatore, è uno dei modelli mentali più utili di tutta la programmazione.



Questo contrasto mette in luce un compromesso di progettazione deliberato. Un analizzatore indulgente come quello dell'HTML privilegia la resilienza e il fatto che l'utente veda sempre qualcosa, al prezzo di lasciar passare in silenzio gli errori. Un analizzatore rigoroso come quello dell'XML privilegia la correttezza e la prevedibilità, al prezzo di rifiutare in partenza un ingresso imperfetto. Nessuno è universalmente migliore; ciascuno si addice al compito per cui è stato concepito, e riconoscere quale filosofia segue un formato ti dice molto sul suo comportamento.