Fasi di un Compilatore

Documenti analoghi
Linguaggi e Ambienti di Programmazione

Corso di Fondamenti di Informatica Linguaggi di Programmazione

Automi e Linguaggi Formali

I Linguaggi di Programmazione

Il Modello di un Compilatore. La costruzione di un compilatore per un particolare linguaggio di programmazione e' abbastanza complessa.

Il Modello di un Compilatore. La costruzione di un compilatore per un particolare linguaggio di programmazione e' abbastanza complessa.

Sommario Linguaggi, messaggi e comunicazione. Introduzione ai Linguaggi di Programmazione. Linguaggio (1) Linguaggio (2)

Linguaggi, messaggi e comunicazione Traduzione di programmi Interpreti e compilatori Introduzione al processo di compilazione

COMPILATORI: MODELLO La costruzione di un compilatore per un particolare linguaggio di programmazione è complessa. La complessità dipende dal linguagg

Compilatore. Messaggi di errore

Lezione 6 Introduzione al C++ Mauro Piccolo

Sommario Linguaggi, messaggi e comunicazione. Introduzione ai Linguaggi di Programmazione. Linguaggio. Messaggio

Fondamenti d Informatica: linguaggi formali. Barbara Re, Phd

Analizzatori Lessicali con JLex. Giuseppe Morelli

ASTRAZIONE. Sono indipendenti dalla macchina hardware sottostante ASTRAZIONE 1

Programma del corso. Elementi di Programmazione. Introduzione agli algoritmi. Rappresentazione delle Informazioni. Architettura del calcolatore

Analizzatore lessicale o scanner. Lo scanner rappresenta un'interfaccia fra il programma sorgente e l'analizzatore sintattico o parser.

LA CODIFICA DELLE INFORMAZIONI

Analizzatore lessicale

Traduzione guidata dalla sintassi

Linguaggi e Traduttori: Analisi sintattica

Esempio. Le istruzioni corrispondono a quelle di sopra, ma sono scritte in modo simbolico. E indipendente dalla machina

Linguaggi di Programmazione

Strutture dati e loro organizzazione. Gabriella Trucco

Architettura di un linguaggio dinamico

Linguaggi di Programmazione

Elementi di programmazione

Le istruzioni corrispondono univocamente a quelle macchina, ma vengono espresse tramite nomi simbolici i (parole chiave)

Corso di Laurea in Informatica. Dipartimento di Matematica e Informatica. Note del corso di Linguaggi di Programmazione e Compilatori

COMPILATORI: MODELLO COMPILATORI: MODELLO ANALIZZATORE LESSICALE. Si noti che le variabili sono associate allo stesso numero identificativo

LINGUAGGI DI ALTO LIVELLO. Si basano su una macchina virtuale le cui mosse non sono quelle della macchina hardware

Octave. Luca Abeni. Informatica Luca Abeni 1 / 21

LINGUAGGI DI ALTO LIVELLO

Funzioni, Stack e Visibilità delle Variabili in C

PROGRAMMAZIONE Macchine astratte, linguaggi, interpretazione e compilazione

Elementi di programmazione

Corso di Laurea Magistrale in Ingegneria Informatica A.A Linguaggi Formali e Compilatori. Introduzione. Giacomo PISCITELLI

Corso di Fondamenti di Informatica Linguaggi di Programmazione

Informatica Generale Andrea Corradini Ancora sui linguaggi di programmazione

Elementi di programmazione

La Programmazione. Cos è la programmazione? Concetti preliminari

Semantica statica e dinamica

Linguaggi e Traduttori: Analisi lessicale

Linguaggi di Programmazione

Scopo del progetto è la costruzione di un compilatore per il linguaggio descritto qui di seguito.

Analizzatore Lessicale Parte I Scanner

Corso di Laurea Magistrale in Ingegneria Informatica A.A Linguaggi Formali e Compilatori. Introduzione. Giacomo PISCITELLI

o Introduzione agli algoritmi o Rappresentazione delle Informazioni o Architettura del calcolatore o Reti di Calcolatori

LINGUAGGI DI ALTO LIVELLO

Macchine astratte, linguaggi, interpretazione, compilazione

Analisi lessicale (scanner)

DAGLI ALGORITMI AI LINGUAGGI. Linguaggi di Programmazione

Programmazione C Massimo Callisto De Donato

Informatica 3. LEZIONE 2: Sintassi e semantica

Prof. Pagani Corrado INTRODUZIONE AL LINGUAGGIO C

Analisi lessicale (scanner)

Paolo Bison. Fondamenti di Informatica Ingegneria Meccanica Università di Padova A.A. 2008/09

Dispensa 1. Da un punto di vista logico l architettura di un compilatore si può suddividere in due parti: Analisi e Sintesi.

Programmazione II. Lezione 7. Daniele Sgandurra 9/11/2010.

Introduzione. Informatica B. Daniele Loiacono

Introduzione alla programmazione in C++

ciclo di vita della soluzione (informatica) d un problema

Descrizione delle operazioni di calcolo. Espressioni costanti semplici

Traduzione guidata dalla sintassi. Attributi e Definizioni guidate dalla sintassi

Intro. Traduzione guidata dalla sintassi. Attributi. Due notazioni a diversi livelli. Due notazioni a diversi livelli. Il flusso concettuale

File binari e file di testo

PROBLEMI ALGORITMI E PROGRAMMAZIONE

Unità Didattica 2 I Linguaggi di Programmazione

Struttura dei programmi C

Corso di Informatica

Informatica 3. Informatica 3. LEZIONE 2: Sintassi e semantica. Lezione 2- Modulo 1. Le componenti di un linguaggio di programmazione

STORIA E CARATTERISTICHE

Le basi del linguaggio Java

Ingegneria del software

Grammatiche Parse trees Lezione del 17/10/2012

Progetto Laboratorio Programmazione Parte 2: Analizzatore sintattico di espressioni

Yet Another Compiler-Compiler. Generazione automatica di analizzatori sintattici

LINGUAGGI DI ALTO LIVELLO

Indice PARTE A. Prefazione Gli Autori Ringraziamenti dell Editore La storia del C. Capitolo 1 Computer 1. Capitolo 2 Sistemi operativi 21 XVII XXIX

6 - Blocchi e cicli. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

1

Programmazione. Dipartimento di Matematica. Ing. Cristiano Gregnanin. 29 febbraio Corso di laurea in Matematica

Linguaggi di programmazione

Cos è un algoritmo. Si dice algoritmo la descrizione di un metodo di soluzione di un problema che sia

Primi passi col linguaggio C

Informatica Problema Algoritmo Programma

Implementazione di DFA in C

Corso di Linguaggi di Programmazione + Laboratorio

Semantica e traduzione guidata dalla sintassi (cenni)

Gestione degli errori

Corso di Linguaggi di Programmazione

Interpreti, compilatori e semantica operazionale

Capitolo 6. Linguaggi di Programmazione. Mauro Giacomini Pearson Addison-Wesley. All rights reserved

Introduzione alla programmazione. Alice Pavarani

Transcript:

Dipartimento di Matematica e Informatica Università di Camerino

Un implementazione compilativa di un linguaggio di programmazione viene realizzata tramite un programma che prende il nome di compilatore Un compilatore è un programmazione che prende in input un altro programma P scritto nel linguaggio sorgente e restituisce in output un programma P funzionalmente equivalente a P, ma scritto nel linguaggio target (linguaggio della macchina scelta per l implementazione) sorgente Compilatore target errori

La scrittura di un compilatore è un compito abbastanza complesso Ad esempio, la scrittura del primo compilatore Fortran (fine anni 50) ha richiesto 18 anni di lavoro da parte di uno staff Fortunatamente, nel corso degli anni, sono state sviluppate delle tecniche sistematiche per lo sviluppo delle più importanti fasi del processo di compilazione Oggi, la conoscienza di tecniche efficaci per la scrittura di un compilatore è molto vasta e strutturata Esistono linguaggi di programmazione (es. C), ambienti di programmazione e tools che facilitano tale compito (generazione automatica a partire dalle specifiche delle varie parti del linguaggio sorgente)

Processo di compilazione È concettualmente suddiviso in due fasi: una fase di analisi (front-end) ed una fase di sintesi sintesi (back-end) La fase di analisi si occupa di dare una struttura al codice e creare una sua rappresentazione intermedia: le operazioni indicate nel programma sorgente vengono identificate e raggruppate in una struttura ad albero (syntax tree) La fase di sintesi genera il codice nel linguaggio target a partire dalla rappresentazione intermedia costruita nella fase procedente

Analisi lineare (analisi lessicale, scanning) Lo stream (sequenza) di caratteri che costituisce il programma in input viene letto e raggruppato in sequenze di caratteri con significato comune detti lessemi; per ognuno di questi l analizzatore lessicale produce in output un token identificatori, parole chiave (if, while, int), operatori, simboli di punteggiatura cerchiamo le parole del nostro linguaggio Analisi gerarchica (analisi sintattica, parsing) I token identificati nella fase precedente vengono raggruppati gerarchicamente tramite delle strutture ad albero che specificano la struttura sintattica delle frasi del programma cerchiamo di mettere insieme le parole identificate in fase di analisi lineare per formare parole sintatticamente corrette Analisi semantica Verifichiamo che le varie parti del programma siano consistenti l una con l altra, a seconda del loro significato

Analisi lineare (analisi lessicale, scanning) Lo stream (sequenza) di caratteri che costituisce il programma in input viene letto e raggruppato in sequenze di caratteri con significato comune detti lessemi; per ognuno di questi l analizzatore lessicale produce in output un token identificatori, parole chiave (if, while, int), operatori, simboli di punteggiatura cerchiamo le parole del nostro linguaggio Analisi gerarchica (analisi sintattica, parsing) I token identificati nella fase precedente vengono raggruppati gerarchicamente tramite delle strutture ad albero che specificano la struttura sintattica delle frasi del programma cerchiamo di mettere insieme le parole identificate in fase di analisi lineare per formare parole sintatticamente corrette Analisi semantica Verifichiamo che le varie parti del programma siano consistenti l una con l altra, a seconda del loro significato

Analisi lineare (analisi lessicale, scanning) Lo stream (sequenza) di caratteri che costituisce il programma in input viene letto e raggruppato in sequenze di caratteri con significato comune detti lessemi; per ognuno di questi l analizzatore lessicale produce in output un token identificatori, parole chiave (if, while, int), operatori, simboli di punteggiatura cerchiamo le parole del nostro linguaggio Analisi gerarchica (analisi sintattica, parsing) I token identificati nella fase precedente vengono raggruppati gerarchicamente tramite delle strutture ad albero che specificano la struttura sintattica delle frasi del programma cerchiamo di mettere insieme le parole identificate in fase di analisi lineare per formare parole sintatticamente corrette Analisi semantica Verifichiamo che le varie parti del programma siano consistenti l una con l altra, a seconda del loro significato

Analisi Lessicale Consideriamo, la sequenza di caratteri pos := init + rate 60 Lo scanning di questa sequenza identifica i seguenti lessemi: 1 l identificatore pos 2 l operatore di assegnamento := 3 l identificatore init 4 l operatore + 5 l identificatore rate 6 l operatore 7 il numero 60 La sequenza di tokens prodotti in output è : id, 1 := id, 2 + id, 3 60 Blank, tabulazioni, newline, e commenti (utili al programmatore ma ignorati dal compilatore) vengono eliminati durante la fase di analisi lessicale

Analisi Sintattica I token individuati durante la fase di analisi lessicale vengono raggruppati in frasi grammaticali Le frasi grammaticali sono rappresentate mediante syntax-tree (una variante degli alberi di derivazione): sulle foglie troviamo gli operandi, sui nodi interni le operazioni Figura: Syntax tree per la stringa id 1 := id 2 + id 3 60

Analisi Lessicale vs Analisi Sintattica La divisione tra le fasi di analisi lessicale e analisi sintattica è in qualche modo arbitraria e dipende, essenzialmente, dalle scelte del progettista L obiettivo è quello di semplificare per quanto possibile l analisi sintattica Un fattore discriminante è, in genere, la ricorsione Per riconoscere i token di un dato linguaggio è, in generale, sufficiente una scansione lineare del programma in input es: per riconoscere identificatori (stringhe che cominciano con una lettere e continuano con lettere e/o numeri) basta riconocere la prima lettera e continuare a leggere finchè non si incontra un carattere che non è una lettera oppure un numero La scansione lineare non è, invece, abbastanza potente per poter identificare espressioni e statements (costrutti tipicamente ricorsivi) es: non si possono associare in maniera corretta i begin e gli end dei costrutti se non si da una struttura gerarchica o annidata all input

Analisi Semantica Controlla che non ci siano errori semantici e acquisisce informazioni sui tipi che verranno usate nella fase di generazione del codice La rappresentazione intermedia (generata dalla fase di analisi sintattica) viene usata per identificare operatori ed operandi di espressioni e statements Un componente importante è la fase di type checking: il compilatore verifica che ogni operatore sia applicato ad operandi consentiti dalla specifica del linguaggio Può dar luogo ad: errori, es: uso di numeri reali per indicizzare array conversioni di tipo: se, nell espressione id 1 := id 2 + id 3 60, il valore di id 3 è un numero reale, l intero 60 viene automaticamente convertito in un reale in questo caso un nuovo nodo viene aggiunto al syntax tree

Analisi Semantica Figura: Conversione automatiche di tipo

Processo di compilazione programma sorgente Analizzatore lessicale Analizzatore sintattico Gestore Tabella dei simboli Analizzatore semantico Generatore del codice intermedio Gestore degli errori Ottimizzatore del codice Generatore del codice target programma target

Tabella dei simboli Uno dei ruoli fondamentali di un compilatore è quello di memorizzare tutti gli identificatori usati nel programma ed i relativi attributi tipo, valore, scope,... per nomi di procedure: il numero e il tipo dei parametri, la modalità di passaggio dei parametri, il tipo di ritorno (se esiste),... La tabella dei simboli è una struttura dati che contiene un record per ogni identificatore; i campi di questo vengono usati per memorizzare i diversi attributi di ciascun identificatore Scopo: reperire tutte le informazioni relative ad un identificatore Ogni nuovo identificatore identificato durante la fase di analisi lessicale viene aggiunto alla tabella dei simboli non tutti gli attributi possono essere identificati in fase di scanning informazioni relative ai tipi: analisi semantica informazioni relative al numero di byte allocati: generazione del codice

Gestione degli errori Altro ruolo fondamentale è il riconoscimento e la segnalazione degli errori Ogni fase è in grado di rilevare solo una particolare classe di errori errori lessicali: la sequenza di caratteri esaminata non fa match con nessun token errori sintattici: uno stream di tokens viola le regole sintattiche del linguaggio errori semantici: costrutti sintatticamente corretti richiedono operazioni non consentite dagli operandi in gioco, es. somma tra un intero ed un array Le fasi di analisi lessicale e sintattica sono quelle che devono fronteggiare il maggior numero di errori Gli errori devono essere gestiti in modo da consentire il proseguimento del processo di compilazione: immaginate un compilatore che si blocca ogni volta che omettete un ;

Generazione del codice intermedio Terminata la fase di analisi, alcuni compilatori generano una rappresentazione intermedia esplicita del programma sorgente Possiamo pensare a questa rappresentazione come ad un programma scritto nel linguaggio di una macchina astratta poco distante dalla macchina ospite verso cui stiamo compilando Le principali proprietà di questo linguaggio sono le seguenti: semplice da produrre semplice da tradurre nel linguaggio della macchina ospite Esistono diverse rappresentazioni intermedie, una di queste è il codice a tre indirizzi (three-address-code)

Generazione del codice intermedio Figura: Generazione codice intermedio un esempio

Generazione del codice intermedio Generatore prende in input l albero di derivazione generato durante la fase di analisi semantica e restituisce il seguente three-address code temp 1 := inttoreal(60) temp 2 := id 3 * temp 1 temp 3 := id 2 + temp 2 id 1 := temp 3 Caratteristiche del three-address code: 1 ogni istruzione ha al più un operatore oltre all operatore di assegnamento 2 viene generato un nome temporaneo per denotare il valore calcolato da ogni istruzione 3 alcune istruzioni possono avere un solo operando

Ottimizzazione del codice Ottimizzare il codice prodotto in maniera da renderlo più efficiente quando sarà eseguito sulla macchina ospite (1) e (2) temp 1 := id 3 * 60.0 (3) e (4) id 1 := id 2 + temp 1 (1) temp 1 := inttoreal(60) (2) temp 2 := id 3 * temp 1 (3) temp 3 := id 2 + temp 2 (4) id 1 := temp 3 Queste semplici ottimizzazioni del codice prodotto non rallentano il processo di compilazione riescono a migliorare sensibilmente il tempo di esecuzione del programma

Generatore del codice target Genera il codice target a partire dal codice intermedio ottimizzato Asumendo che il linguaggio target sia il codice assembly temp 1 := id 3 * 60.0 id 1 := id 2 + temp 1 MOV id 3, R2 MUL i#60.0, R2 MOV id 2, R1 ADD R2, R1 MOV R1, id 1