1. CASO DI STUDIO:
LINGUAGGI
DI
PROGRAMMAZIONE
ANNO 2006/07
Pag. 1 di 15
2. Documentazione Caso di studio Linguaggi di programmazione
Data la grammatica di un (frammento di un) linguaggio di programmazione, mediante strumenti
automatici (ANTLR o JavaCC), realizzare in linguaggio Java un programma che implementi:
uno scanner per un linguaggio di programmazione di cui viene documentato formalmente
il vocabolario
un parser ricorsivo discendente per un frammento di linguaggio di programmazione
ANALISI
L’obiettivo è scrivere una grammatica dalla quale generare attraverso JavaCC le classi Lexer e
Parser che compongono l’analizzatore sintattico del linguaggio di programmazione che si propone.
Si parte dalla scelta del linguaggio di programmazione oggetto del caso di studio e si fornisce
l’alfabeto.
Il linguaggio di programmazione posto all’attenzione è il Pascal con alcuni richiami di Java.
Il linguaggi da implementare sarà una forma italianizzata dei linguaggi di programmazione appena
menzionati.
Tutte le parole chiave sono in lingua italiana per un più facile utilizzo dello strumento stesso.
I costrutti utilizzati sono :
• begin … end che italianizzato diverrà inizio … fine ; questo è preso dal linguaggio pascal ed
è utile al fine di rendere più chiara la lettura del codice ed eliminare l’ambiguità legata al
costrutto if … then … else.
Pag. 2 di 15
3. • If… then … else italianizzato se … allora … altrimenti ; costrutto di selezione .
• while… do che diverrà fintanto che(condizione) fai… seguita dal costrutto inizio … fine
costrutto di ciclo a controllo in testa. La sua sintassi è presa dal linguaggio Java.
• repeat … until(condizione) che diverrà ripeti … finchè (condizione) ; costrutto a ciclo a
controllo in coda. Anche questo è preso dal linguaggio java.
• for (inizializzazione, condizione, passo) …. ; sarà scritto come Per (inizializzazione,
condizione, passo). Sintassi dal linguaggio Java.
Per implementare la sintassi delle espressioni matematiche varrà la seguente forma :
variabile = variabile | numero reale | espressione matematica, dove l’espressione aritmetica è
formata da operazioni aritmetiche tra variabili. Per definire l’ordine delle operazioni si potranno
usare le parentesi tonde.
Saranno previsti inoltre comandi per le operazioni base di un linguaggio di programmazione quale
la stampa a video di una variabile e l’acquisizione da tastiera di una variabile .
Le variabili che il compilatore progettato tratterà saranno dei seguenti tipi:
• Interi
• Reali
• Reali a singola precisione
• Reali a doppia precisione
• Carattere
• Stringa
• Booleano
• Puntatore
Un identificatore sarà formato da un insieme di caratteri. Tutte le lettere devono essere
maiuscole.
Le parole chiave invece dovranno essere scritte interamente in minuscolo poiché il linguaggio sarà
case sensitive.
Inoltre la sintassi di un programma sarà divisa in 2 parti:
• Dichiarazione delle variabili
Pag. 3 di 15
4. • Operazioni da eseguire (assegnazioni, espressioni matematiche, cicli, stampe,
acquisizioni,condizioni)
Nella prima parte avremo, dopo aver dichiarato l’inizio del programma con la parola chiave inizio
del costrutto inizio … fine, la dichiarazione delle variabili. In questo spazio potranno essere
dichiarate tutte le variabili da utilizzare fino a che non verrà digitata la prima istruzione accettata
dal linguaggio che non sia una dichiarazione di variabile.
Avvenuto questo inizierà la seconda parte del programma dove se ci sarà una dichiarazione di
variabile il parser rileverà un errore e terminerà. In caso contrario continuerà a controllare la
sintassi di tutte le istruzioni digitate e dopo l’ultima istruzione deve essere presente la parola
chiave fine del costrutto inizio … fine. Se tutte le istruzioni digitate sono accettabili secondo la
grammatica il parser terminerà la scansione con successo.
Se nelle istruzioni digitate ci saranno delle condizioni o dei cicli, al loro interno sarà possibile
dichiarare altre variabili che verranno considerate locali al blocco di istruzioni.
Per concludere, quando si verificherà un errore la sua gestione sarà disponibile in lingua italiana.
PROGETTAZIONE
Grammatica del linguaggio in notazione (E)BNF:
<START> ::= inizio; [ <CODICE> ] fine;
<CODICE> ::= [ <DICHIARAZIONE> ] <CODICE1>
<DICHIARAZIONE> ::= <TIPO> <IDENTIFICATORE>; [ <DICHIARAZIONE> ]
<TIPO> ::= intero | reale | stringa | doppiaprecisione | singolaprecisione | carattere | booleano |
puntatore
Pag. 4 di 15
6. CODIFICA:
/* Caso di studio di linguaggi di programmazione*/
options
{
STATIC = false; // default TRUE
LOOKAHEAD = 2; // default 1
IGNORE_CASE = true; // default false
}
Pag. 6 di 15
7. PARSER_BEGIN (casodistudio)
// eventuale dichiarazione di package
// eventuale lista di import
public class casodistudio {
public static void main(String args[]) throws ParseException {
casodistudio parser = new casodistudio(System.in);
parser.start();
}
}
PARSER_END (casodistudio)
SKIP : { " " | "t" | "n" | "r" }
SKIP:
{
<"/*"> : COMMENTO //gestione dei commenti
}
<COMMENTO>
SKIP:
{ <"/*"> : DEFAULT //ritorno dalla gestione dei commenti
| <~[ ]>
}
TOKEN :
{
<NUM: (["0"-"9"])+> //token dei numeri
| <PIU: "+"> //token della somma
| <MENO: "-"> //token della sottrazione
| <PER: "*"> //token della moltiplicazione
| <DIV: "/"> //token della divisione
Pag. 7 di 15
8. | <PARAP: "("> //token della parentesi aperta
| <PARCH: ")"> //token della parentesi chiusa
| <ELSE: "altrimenti"> //token del ramo else
| <IF: "se"> //token dell' if
| <FOR: "per"> //token del for
| <REPEAT: "ripeti"> //token del repeat
| <UNTIL: "finche"> //token del until
| <WHILE: "fintanto che"> //token del while
| <DO: "fai"> //token del do
| <THEN: "allora"> //token del then
| <SEMICOLON: ";"> //token del semicolon
| <STAMPA: "stampa"> //token per la stampa
| <LEGGI: "leggi"> //token per la lettura
| <INIZIO: "inizio"> //token di inizio
| <FINE: "fine"> //token per la fine
| <UGUALE: "="> //token per l'uguale
| <MINORESR: "<"> //token per il minore stretto
| <MAGGIORESR: ">"> //token per la maggiore stretto
| <MAGGIORE: ">="|"=>"> //token per il maggiore uguale
| <MINORE: "<="|"=<"> //token per il minore uguale
| <DIVERSO: "!="|"=!"> //token per il diverso
| <EQUIVALENTE: "=="> //token per l'equivalenza
| <INT: "intero"> //token per gli integer
| <REAL: "reale"> //token per i real
| <STRING: "stringa"> //token per le string
| <CHAR: "carattere"> //token per i char
| <BOOLEAN: "booleano"> //token per i boolean
| <FLOAT: "singolaprecisione"> //token per i float
| <DOUBLE: "doppiaprecisione">//token per i double
| <POINTER:"puntatore"> //token per i puntatori
Pag. 8 di 15
9. | <VIR: ","> //token per la virgola
| <IDENTIFICATORE: (["A"-"Z"])+>//token per la gestione delle variabili
}
void start() :
{}
{ <INIZIO> <SEMICOLON> [codice()] <FINE> <SEMICOLON> } //regola che definisce
come deve iniziare un programma
void codice() :
{}
{ [dichiarazione()] codice1() } //regola che definisce che il programma deve essere diviso in
2 parti una destinata alla dichiarazione e uno destinato al codice
void dichiarazione() :
{}
{ tipo() <IDENTIFICATORE> <SEMICOLON> [dichiarazione()] } //regola che definisce la
dichiarazione
void tipo() :
{}
{ <INT> | <REAL> | <STRING> | <CHAR> | <BOOLEAN> | <FLOAT> | <DOUBLE> | <POINTER>
} //regola che definisce i tipi
void codice1() :
{}
Pag. 9 di 15
10. { calcolo() <SEMICOLON> [codice1()] | <FOR> <PARAP> [inizializzazione() <SEMICOLON>]
condizione() <SEMICOLON> calcolo() <PARCH> start() [codice1()] | <REPEAT> start() <UNTIL>
<PARAP> condizione() <PARCH> [codice1()] | <WHILE> <PARAP> condizione() <PARCH> <DO>
start() [codice1()] | <IF> <PARAP> condizione() <PARCH> <THEN> start() [<ELSE> start()] [codice1()]
| <STAMPA> <PARAP> <IDENTIFICATORE> <PARCH> <SEMICOLON> [ codice1() ] | <LEGGI>
<IDENTIFICATORE> <SEMICOLON> [codice1()] } //regole che definiscono i costrutti del
linguaggio di programmazione
//regole per il calcolo
void calcolo() :
{}
{ <IDENTIFICATORE> <UGUALE> calcolo1() } //regola che definisce l'inizio di
una espressione matematica
void calcolo1() :
{}
{ <PARAP> calcolo1() <PARCH> [ operazioni() calcolo1() ] | calcolo2() } //regola che
definisce la regolarità delle parentesi tonde
void calcolo2() :
{}
{ <IDENTIFICATORE> [ operazioni() calcolo1() ] | reale() [ operazioni() calcolo1() ] } //regola
che definisce una espressione matematica semplice
void operazioni() :
{}
{ <DIV> | <PIU> | <MENO> | <PER> } //regola che definisce il tipo di
operazione che si possono compiere nelle operazioni matematiche
//regole per i numeri reali
Pag. 10 di 15
11. void reale():
{}
{ (<NUM>)+[<VIR>(<NUM>)+]} //regole che definiscono come
creare un numero reale
//regole per i costrutti
void inizializzazione() :
{}
{ tipo() <IDENTIFICATORE> } //regola che definisce la dichiarazione di
una variabile
void condizione() :
{}
{ <IDENTIFICATORE> rapporto() calcolo1() } //regola che definisce la forma della
condizione
void rapporto() :
{}
{ <MAGGIORESR> | <MINORESR> | <MAGGIORE> | <MINORE> | <DIVERSO> |
<EQUIVALENTE> }//regola che definisce il tipo di condizione
TEST:
Primo test:
-inserisco una funzione matematica all ' interno del codice con utilizzo di parentesi per definire le
precedenze tra le varie operazioni:
Pag. 11 di 15
12. Secondo test:
-inserisco il costrutto for all' interno del codice definendo le variabili e chiudendo il corpo del
costrutto all'interno di inizio e fine;
Terzo test:
-inserisco il costrutto repeat-until all' interno del codice definendo le variabili e chiudendo il corpo
del costrutto all'interno di inizio e fine;
Pag. 12 di 15
13. Quarto test:
-inserisco il costrutto while do all' interno del codice definendo le variabili e chiudendo il corpo del
costrutto all'interno di inizio e fine;
Quinto test:
-inserisco le operazioni di stampa e di lettura di una variabile all' interno del corpo di un
programma;
Pag. 13 di 15
14. Sesto test:
-inserisco il costrutto if then else all' interno del codice definendo le variabili e chiudendo il corpo
del ramo vero e falso del costrutto all'interno di inizio e fine;
Settimo test:
-in caso di presenza di un errore viene mostrato un messaggio in lingua italiana che indica quale
errore è stato individuato e le coordinate di tale errore.
Pag. 14 di 15
15. Viene anche mostrato un messaggio che cosa ci si sarebbe aspettato al posto dell'errore
commesso.
Pag. 15 di 15