Compilatori 2007
docente: Fausto Spoto fausto.spoto@univr.it
collaboratore didattico: Andrea Turrini
Il compilatore Kitten versione 9/1/2007 (funziona solo su Java 1.5)
L'analizzatore di grammatiche GRAN e la sua
documentazione, di
Enrico Masserdotti: emasserdotti AT gmail DOT com
Documentazione della libreria BCEL
Sito da cui scaricare il graphviz per il formato .dot
Il manuale ufficiale della Java Virtual Machine
Making Compiler Design Relevant for Students who will (Most Likely) Never Design a Compiler di Saumya Debray
Dispensa
Testi d'esame (alcuni sono troppo vecchi per il programma attuale!):
24 giugno 2002 postscript,
pdf
3 luglio 2002 postscript,
pdf
6 settembre 2002 postscript,
pdf
20 dicembre 2002 postscript,
pdf
2 aprile 2003 postscript,
pdf
23 giugno 2003 postscript,
pdf
25 luglio 2003 postscript,
pdf
24 settembre 2003 postscript,
pdf
10 ottobre 2003 postscript,
pdf
12 dicembre 2003 postscript,
pdf
26 marzo 2004 postscript,
pdf
2 aprile 2004 postscript,
pdf
21 giugno 2004 postscript,
pdf
5 luglio 2004 postscript,
pdf
21 settembre 2004 postscript,
pdf
1 aprile 2005 postscript,
pdf
20 giugno 2005 postscript,
pdf,
soluzione esercizi 2-3
4 luglio 2005 postscript,
pdf,
soluzione esercizi 2-3
5 settembre 2005 postscript,
pdf
5 ottobre 2005 postscript,
pdf
12 dicembre 2005 postscript,
pdf
31 marzo 2006 postscript,
pdf
19 giugno 2006 postscript,
pdf
3 luglio 2006 postscript,
pdf
29 settembre 2006 postscript,
pdf
5 ottobre 2006 postscript,
pdf
31 ottobre 2006 postscript,
pdf
15 dicembre 2006 postscript,
pdf
27 giugno 2007 postscript,
pdf
Lezione 1 (9 gennaio 2007)
introduzione al corso
i compilatori
esempi di programmi Kitten
espressioni, comandi, valori, tipi
relazione di sottotipo
Lezione 2 (9 gennaio 2007)
analisi lessicale, token, espressioni regolari
JLex: specifica di token e azioni
da espressioni regolari ad automa finito non deterministico e poi deterministico
Laboratorio 1 (12 gennaio 2007)
Si salvi questo codice
nella directory testcases. Quindi si completi la classe
Primes.kit in modo da farle implementare la lista infinita
dei numeri primi e farli stampare al metodo main
(Soluzione)
Lezione 3 (16 gennaio 2007)
automa per più espressioni regolari
grammatiche
grammatica per Kitten
leftvalue e rightvalue
introduzione al parsing a discesa ricorsiva
Lezione 4 (17 gennaio 2007)
forme sentenziali annullabili
definizione composizionale dell'annullabilità
calcolo degli annullabili
inizi di una forma sentenziale
definizione composizionale degli inizi
Laboratorio 2 (19 gennaio 2007)
Si aggiungano a Kitten
i token TRY, THROW, THROWS e CATCH,
che rappresentano le stringhe omonime. Occorre sia modificare
lexical/Kitten.lex che l'enumerazione in syntactical/sym.java
(si ricordi di eseguire
make lexical alla fine). Si verifichi che tali token siano
effettivamente riconosciuti provando a compilare
questo file Kitten.
Lezione 5 (23 gennaio 2007)
calcolo degli inizi per i non terminali
definizione dei seguiti
calcolo dei seguiti dei non terminali
insiemi discriminanti per il parsing a discesa ricorsiva
tabella e parsing LL(1)
Lezione 6 (24 gennaio 2007)
item LR(0)
chiusura di un insieme di item e stati LR(0)
automa a pila: azioni di spostamento, riduzione, accettazione
Laboratorio 3 (26 gennaio 2007)
Modificate il makefile in modo da ammettere al più un
conflitto: cercate l'invocazione di java_cup.Main e aggiungete
subito dopo -expect 1
Modificate quindi la grammatica di Kitten in modo da
aggiungere il comando throw X che lancia il valore di
X; la possibilità di decorare l'intestazione di un
metodo o costruttore con throws list dove list è
una sequenza non vuota di tipi separati da virgola; il comando
try C catch T1 ID1 C1 ... catch Tn IDn Cn che esegue C
e se esso lancia un'eccezione ne confronta il tipo con i Ti:
il primo Ti compatibile con l'eccezione
comporta l'esecuzione del corrispondente Ci (non imponete
le parentesi graffe nella sintassi!)
Non date regole semantiche nelle produzioni che aggiungete.
Ricordatevi alla fine di eseguire un make syntactical.
Dovreste essere capaci di effettuare senza problemi il parsing del
file di esempio.
Lezione 7 (30 gennaio 2007)
costruzione della tabella LR(0)
esempio di parsing LR(0)
il parsing SLR
esempio di parsing SLR
Lezione 8 (31 gennaio 2007)
item LR(1)
costruzione della tabella LR(1)
Lezione 9 (2 febbraio 2007)
Automa e tabella LALR(1)
Gerarchia di parsing delle grammatiche
Risoluzione dei conflitti con JavaCup
Il parsing con grammatiche ambigue: il caso delle espressioni aritmetiche
Lezione 10 (6 febbraio 2007)
Il parsing con grammatiche ambigue: il caso dell'if/then/else
Azioni semantiche associate alle produzioni
Esempi di decorazione di una grammatica con azioni semantiche
Uso delle azioni semantiche per costruire la sintassi astratta del
codice sorgente
Struttura e classi della sintassi astratta Kitten
Lezione 11 (7 febbraio 2007)
Algoritmi a discesa ricorsiva sulla sintassi astratta
Determinazione delle variabili di un'espressione o comando
Lezione 12 (9 febbraio 2007)
Determinazione delle variabili dichiarate ma non usate
Determinazione del codice morto
Rappresentazione grafica in dot della sintassi astratta
Analisi semantica: sue funzioni
Classi per i tipi semantici di Kitten
Implementazione della relazione di sottotipaggio
Lezione 13 (13 febbraio 2007)
Analisi semantica delle espressioni di tipo Kitten
Analisi semantica delle espressioni Kitten e sua implementazione
Lezione 14 (14 febbraio 2007)
Analisi semantica dei comandi Kitten e sua implementazione
Laboratorio 4 (16 febbraio 2007)
- Partite da questo schema per scrivere
le classi di sintassi astratta per i nuovi elementi
che avete aggiunto alla sintassi Kitten. Dovrete modificare
anche la sintassi astratta per le dichiarazioni di metodi e costruttori
poiché avete aggiunto una lista di tipi.
Per adesso non specificate il metodo di analisi semantica
- Aggiungete in syntactical/Kitten.cup le azioni semantiche
per istanziare le nuove classi di sintassi astratta
- Eseguite un make syntactical
- Verificate che l'albero di sintassi astratta sia generato correttamente:
compilate il solito esempio e poi
dot -Tps testcases/file.dot|kghostview -
per i vari file dot che vengono generati dalla compilazione
- Specificate il metodo di analisi semantica per i nuovi elementi di
sintassi aggiunti a Kitten: non preoccupatevi al momento di verificare che
un metodo lanci solo i tipi che esso dichiara di lanciare
- Eseguite un make semantical e verificate che
il file di esempio sia compilato senza errori semantici
Lezione 15 (20 febbraio 2007)
Esercizi sull'analisi semantica
Introduzione alla generazione del Kitten bytecode
I bytecode Kitten
Lezione 16 (21 febbraio 2007)
I bytecode per la chiamata e il ritorno da metodo e costruttore
La compilazione per continuazione
La compilazione attiva delle espressioni: esempi più semplici
Laboratorio 5 (23 febbraio 2007)
Si aggiunga un controllo per il throw che garantisce che il
tipo del valore gettato sia ammesso in tal
punto di programma. A tal fine:
- le types/CodeSignature.java
e le sue due sottoclassi per metodi e costruttori devono avere
spazio per un ulteriore campo thrown che contiene la lista
dei tipi semantici che seguono la clausola throws;
- anche il semantical/TypeChecker.java deve avere un campo
throwables che contiene la lista dei tipi che ammettiamo
possano essere gettati. Tale campo viene inizializzato a thrown
dentro il typeCheck$0() di absyn/MethodDeclaration.java
e absyn/ConstructorDeclaration.java e viene arricchito
nel corpo di un try, che può gettare anche i tipi
dei suoi catch;
- infine il typeCheck$0() del throw deve controllare
che il tipo del valore gettato vada bene rispetto al campo
throwables del type-checker;
- un simile controllo va aggiunto nel typeCheck$0() delle chiamate
di metodo e della creazione di un oggetto;
- Eseguite un make semantical e verificate che il
file di esempio
sia compilato con un unico errore semantico sulla chiamata di
foo1() in main(). Modificatelo
in modo che non segnali più alcun errore semantico.
Lezione 17 (6 marzo 2007)
La compilazione attiva (e quella tipata) delle espressioni
La compilazione condizionale delle espressioni booleane
La compilazione passiva dei leftvalue
Lezione 18 (7 marzo 2007)
La compilazione dei comandi
Lezione 19 (9 marzo 2007)
- Esercizi sulla compilazione
Primo appello il 28 marzo alle 8:30
Progetto valido fino a fine luglio:
- Si aggiungano a Kitten
i token TRY, THROW, THROWS e CATCH,
che rappresentano le stringhe omonime
- Si aggiunga a Kitten il comando throw X che lancia il valore di
X; la possibilità di decorare l'intestazione di un
metodo o costruttore con throws list dove list è
una sequenza non vuota di tipi separati da virgola; il comando
try C catch T1 ID1 C1 ... catch Tn IDn Cn che esegue C
e se esso lancia un'eccezione ne confronta il tipo con i Ti:
il primo Ti compatibile con l'eccezione
comporta l'esecuzione del corrispondente Ci (non imponete
le parentesi graffe nella sintassi!)
- Si scriva la classe di sintassi astratta per gli elementi sintattici
aggiunti al punto precedente
- Si scriva il metodo di controllo dei tipi per gli elementi sintattici
visti sopra.
- Si definisca uno schema a discesa ricorsiva che
ritorna l'insieme dei tipi che potrebbero
essere lanciati da un comando o espressione. Si verifichi che i tipi
lanciati (ma non intercettati!) all'interno del corpo di un costruttore
o metodo siano fra quelli enumerati dalla sua clausola throws
- Si aggiunga un bytecode throw che lancia un'eccezione del tipo
della cima dello stack, i cui elementi, tranne la cima, vengono rimossi;
un bytecode catch T v che intercetta un'eccezione di tipo
T e la lega alla variabile v
Si implementi quindi la generazione del bytecode Kitten per gli elementi
sintattici aggiunti sopra in modo che ogni
bytecode che può sollevare un'eccezione e che si trova all'interno
dello scope di un gestore di eccezione sia alla fine di un blocco
di codice con varie frecce uscenti: una per la continuazione normale
(se c'è) e una
per ogni gestore di eccezione in cui si trova il bytecode. I gestori
di eccezione sono dei blocchi che cominciano con catch T per
il tipo che essi gestiscono.
- [Facoltativo. Solo se vuole più di 8 punti nel progetto]
Si modifichi la generazione del Java bytecode in modo che
i blocchi che hanno più frecce uscenti, alcune delle quali
conducono a un
blocco che comincia con catch, comportino la creazione di
opportuni gestori di eccezione Java che eseguono tali blocchi.
Progetto valido da agosto fino a fine dicembre:
10 punti fino a fine ottobre, poi 8 punti
Si aggiunga a Kitten il costrutto for (tipo var: exp) body che lega
iterativamente var, di tipo tipo,
agli elementi di exp ed esegue ogni volta body.
Tale costrutto deve poter funzionare sia se exp contiene un
array sia se contiene un oggetto che estende una classe
Iterable (scrivetela in Kitten) con un metodo
iterator() che restituisce un Iterator
(scrivete in Kitten anche questa classe). Un Iterator
ha due metodi: next(), che restituisce il prossimo
oggetto dell'iterazione, e hasNext(), che determina
se c'è ancora un elemento nell'iterazione.
Si noti che questo operatore for è identico
a quello di Java, per cui basta documentarsi su Java per
comprenderne a fondo la semantica.