Compilatore multi-pass - Multi-pass compiler

Un compilatore multi-pass è un tipo di compilatore che elabora più volte il codice sorgente o l'albero della sintassi astratta di un programma. Questo è in contrasto con un compilatore one-pass , che attraversa il programma solo una volta. Ogni passaggio prende il risultato del passaggio precedente come input e crea un output intermedio. In questo modo, il codice (intermedio) viene migliorato passo dopo passo, fino a quando il passaggio finale produce il codice finale.

I compilatori multi-pass sono talvolta chiamati compilatori estesi , riferendosi alla maggiore portata dei passaggi: possono "vedere" l'intero programma in fase di compilazione, anziché solo una piccola parte di esso. L'ambito più ampio quindi disponibile per questi compilatori consente una migliore generazione del codice (ad es. codice di dimensioni inferiori, codice più veloce) rispetto all'output dei compilatori one-pass, al costo di un maggiore tempo di compilazione e consumo di memoria. Inoltre, alcune lingue non possono essere compilate in un unico passaggio, a causa della loro progettazione.

Tipico compilatore multi-pass

Multi-passcompiler.png

Analisi lessicale

Questa fase di un compilatore a più passaggi consiste nella rimozione di informazioni irrilevanti dal programma sorgente che l'analisi della sintassi non sarà in grado di utilizzare o interpretare. Le informazioni irrilevanti potrebbero includere cose come commenti e spazi bianchi. Oltre a rimuovere le informazioni irrilevanti, l'analisi lessicale determina i token lessicali della lingua. Questo passaggio significa che la dichiarazione anticipata non è generalmente necessaria se viene utilizzato un compilatore a più passaggi. Questa fase è focalizzata sulla suddivisione di una sequenza di caratteri in token con attributi come tipo, tipo, valore e potenzialmente anche altri.

Analisi della sintassi

L'analisi della sintassi è responsabile dell'esame delle regole di sintassi della lingua (spesso come grammatica libera dal contesto ) e della costruzione di una rappresentazione intermedia della lingua. Un esempio di questa rappresentazione intermedia potrebbe essere qualcosa come un albero di sintassi astratto o un grafico aciclico diretto .

Analisi semantica

L'analisi semantica prende la rappresentazione fatta dall'analisi della sintassi e applica regole semantiche alla rappresentazione per assicurarsi che il programma soddisfi i requisiti delle regole semantiche del linguaggio. Ad esempio, nell'esempio seguente nella fase dell'analisi semantica, se il linguaggio richiedesse che le condizioni se le istruzioni fossero espressioni booleane, cond verrebbe verificato il tipo per assicurarsi che sia un'espressione booleana valida.

if(cond) {
 ... 
} else {
 ...
}

Oltre a eseguire l'analisi semantica in questa fase della compilazione, spesso vengono create tabelle di simboli per facilitare la generazione del codice.

Generazione del codice

Questa fase finale di un tipico compilatore converte la rappresentazione intermedia del programma in un insieme eseguibile di istruzioni (spesso assembly ). Quest'ultima fase è l'unica fase della compilazione che dipende dalla macchina. In questa fase della compilazione possono essere eseguite anche ottimizzazioni che rendono il programma più efficiente.

Altri passaggi del compilatore includono la fase di generazione del codice intermedia che avviene prima della generazione del codice e la fase di ottimizzazione del codice che può avvenire quando viene scritto il programma sorgente, o dopo la fase di generazione del codice intermedia o dopo la fase di generazione del codice.

Vantaggi dei compilatori multi-pass

Indipendente dalla macchina : poiché i passaggi multipli includono una struttura modulare e la generazione del codice disaccoppiata dagli altri passaggi del compilatore, i passaggi possono essere riutilizzati per hardware/macchine diversi.

Linguaggi più espressivi : più passaggi evitano la necessità di dichiarazioni in avanti, consentendo l'implementazione elegante della ricorsione reciproca. I principali esempi di linguaggi che richiedono dichiarazioni anticipate a causa del requisito di essere compilabili in un unico passaggio includono C e Pascal , mentre Java non ha dichiarazioni anticipate.

Riferimenti

  • Bornat, Richard , Comprensione e scrittura dei compilatori: una guida fai-da-te , Macmillan Publishing, 1979. ISBN  0-333-21732-2
  • Bent Thomsen, Languages ​​and Compilers SProg og Overseattere , Dipartimento di Informatica, Università di Aalborg