LEZIONE 2: Sintassi e semantica Informatica 3

Informatica 3
LEZIONE 2: Sintassi e semantica
• Modulo 1: Introduzione ai concetti di sintassi
e semantica
• Modulo 2: Il concetto di binding
• Modulo 3: Variabili
• Modulo 4: Routine – Convenzioni dei nomi
Politecnico di Milano - Prof. Sara Comai
1
Informatica 3
Lezione 2- Modulo 1
Introduzione ai concetti di sintassi e
semantica
Politecnico di Milano - Prof. Sara Comai
2
Le componenti di un linguaggio di
programmazione
• Un linguaggio di programmazione è una
notazione formale caratterizzata da due
componenti:
– Sintassi: insieme di regole formali che specificano
la composizione di programmi
• Per determinare se un programma è valido
– Semantica: insieme di regole che specificano il
“significato” di un programma sintatticamente
valido
• Per determinare l’effetto di un programma
– Notazioni formali
– Semantica operazionale: comportamento di un processore
astratto che esegue il programma scritto nel linguaggio di
programmazione
Politecnico di Milano - Prof. Sara Comai
3
Sintassi di un linguaggio
• Sintassi: regole che definiscono le sequenze
valide di simboli
– Frasi come sequenze di parole
– Parole: definite su un alfabeto
• Regole lessicali: insieme di caratteri che costituiscono
l’alfabeto del linguaggio
– Esempi:
• Caratteri maiuscoli e minuscoli differiscono in C/C++ ma
sono identici in Pascal
• L’operatore “diverso” è: != in C/C++ e <> in Pascal
Politecnico di Milano - Prof. Sara Comai
4
EBNF – regole sintattiche
EBNF=Extended Backus Naur Form
Metalinguaggio con metasimboli ::= < > | * +
• Regole sintattiche:
non
terminale
terminale
non terminale
definito da
regole lessicali
<programma>
<istruzione>
::= { <istruzione>* }
::= <assegnamento> | <condizione> |
<ciclo>
<assegnamento> ::= <identificatore> = <espr> ;
<condizione>
::= if <espr> { <istruzione> + } |
if <espr> { <istruzione> + }
else { <istruzione> + }
<ciclo>
::= while <espr> { <istruzione> + }
<espr>
::= <identificatore> | <numero> |
( <espr> ) | <espr> <operatore> <espr>
Politecnico di Milano - Prof. Sara Comai
5
EBNF – regole lessicali
• Regole lessicali:
<operatore>
<identificatore>
<ld>
<numero>
<lettera>
<cifra>
::= + | - | * | / | = | /= | < | > | <= | >=
::= <lettera> <ld>*
::= <lettera> | <cifra>
::= <cifra>+
::= a | b | c | . . . | z
::= 0 | 1 | . . . | 9
Politecnico di Milano - Prof. Sara Comai
6
Diagrammi sintattici
programma
{
}
istruzione
assegnamento
istruzione
condizione
ciclo
assegnamento
identificatore
=
espressione
Politecnico di Milano - Prof. Sara Comai
7
Diagrammi sintattici
condizione
ciclo
while
espressione
{
espressione
if
istruzione
}
else
{
istruzione
}
espressione
{
istruzione
}
espressione
operatore
espressione
identificatore
numero
{
espressione
}
Politecnico di Milano - Prof. Sara Comai
8
Sintassi astratta e concreta
• Costrutti in linguaggi diversi possono avere la stessa
struttura concettuale, ma avere regole lessicali
diverse:
while (x!=y)
{
…
}
while x<>y do
begin
…
end
– Stessa sintassi astratta
– Diversa sintassi concreta
Politecnico di Milano - Prof. Sara Comai
9
Sintassi concreta e usabilità
• <> è più leggibile di !=
• Se il ciclo contiene una singola istruzione le { }
possono essere omesse
– Facile commettere errori!!
while (num!=0){
cin >> num;
}
while (num!=0)
cin >> num;
while num <> 0 do
…
end
Politecnico di Milano - Prof. Sara Comai
10
Informatica 3
Lezione 2- Modulo 2
Il concetto di binding
Politecnico di Milano - Prof. Sara Comai
11
Il concetto di binding
• I programmi sono costituiti da entità
– variabili, routine, istruzioni
• Le entità sono caratterizzate da attributi
– Variabile: nome, tipo, area di memoria
– Routine: nome, parametri, modalità di passaggio
parametri
• Binding: associa un valore agli attributi
• Per ogni entità le informazioni sulle entità
sono contenute in un descrittore
Politecnico di Milano - Prof. Sara Comai
12
Binding
• Concetto fondamentale nella definizione della
semantica di un linguaggio
– Linguaggi diversi presentano
• Un numero di entità diverse
• Un numero di attributi diversi per ogni entità
• Tempi di binding diversi (es. a tempo di compilazione o
esecuzione)
• Stabilità differenti di binding (fissi o modificabili)
– Binding statico: non può essere modificato
– Binding dinamico: modificabile durante l’esecuzione
Politecnico di Milano - Prof. Sara Comai
13
Linguaggi e binding
• Binding definito dalla definizione del linguaggio:
– Esempio: interi Æ insieme di operazioni eseguibili (Fortran,
Ada, C, C++)
• Binding definito dall’implementazione del linguaggio:
– Esempio: interi Æ rappresentazione in memoria (Fortran,
Ada, C, C++)
• Binding definito a tempo di compilazione:
– Esempio: in Pascal il binding degli interi avviene durante la
compilazione
• Binding definito a tempo di esecuzione:
– Maggior parte dei linguaggi di programmazione
– Esempio alle variabili vengono associati dei valori durante
l’esecuzione
Binding dinamico
Politecnico di Milano - Prof. Sara Comai
14
Informatica 3
Lezione 2- Modulo 3
Variabili
Politecnico di Milano - Prof. Sara Comai
15
Variabili
•
I linguaggi di programmazione possono essere visti come
un’astrazione del comportamento dei computer convenzionali:
– Memoria centrale consiste di celle elementari identificate da un
indirizzo
– Il contenuto di una cella rappresenta un valore (codificato)
– Il valore può essere modificato (nuova codifica) durante
l’esecuzione di un programma
– Variabile: astrazione del concetto di cella di memoria
– Nome di variabile: astrazione dell’indirizzo della cella di memoria
– Istruzione di assegnamento: astrazione della modifica del valore di
una cella
•
Formalmente: variabile = <nome, scope, tipo, l-value, r-value>
Politecnico di Milano - Prof. Sara Comai
16
Nome e regole di visibilità
variabile = <nome, scope, tipo, l-value, r-value>
• Nome: stringa di caratteri che denota la variabile
– Solitamente introdotto tramite una dichiarazione
• Visibilità (o scope): insieme di istruzioni a cui il nome
è “noto”
– Dal punto in cui la variabile viene dichiarata fino ad un punto
“di chiusura” successivo
Un programma può manipolare le variabili tramite il loro nome
all’interno del loro scope
Una variabile è visibile con il suo nome all’interno del suo scope
Politecnico di Milano - Prof. Sara Comai
17
Nome e regole di visibilità
• Le regole di binding di una variabile all’interno
del suo scope dipendono dal linguaggio
– Binding statico dello scope
• Lo scope viene definito staticamente, tramite una
dichiarazione implicita o esplicita, senza dover eseguire il
programma
• Maggior parte di linguaggi di programmazione (C/C++)
– Binding dinamico dello scope
• Lo scope viene definito durante l’esecuzione del
programma
• APL, vecchi LISP, SNOBOL4
Politecnico di Milano - Prof. Sara Comai
18
Esempio di binding dinamico dello
scope
{
/* blocco A */
int x;
}
{
/* blocco B */
int x;
•Regole semplici da
implementare
•Implementazione meno
efficiente
}
{
/* blocco C */
x = ...;
}
Esempio: A Æ C; B Æ C
•Programmi difficili da
leggere
Politecnico di Milano - Prof. Sara Comai
19
Tipo
variabile = <nome, scope, tipo, l-value, r-value>
• Tipo di una variabile:
– insieme di valori che possono essere associati alla
variabile
+
– operazioni per creare, accedere, modificare tali
valori
Politecnico di Milano - Prof. Sara Comai
20
Tipi e binding
•
Tipi predefiniti (esempio: int)
– Il nome del tipo viene associato tramite binding alla classe di valori e
all’insieme di operazioni definite dal linguaggio
– I valori e le operazioni vengono associate tramite binding alla
rappresentazione della macchina durante l’implementazione
•
Dichiarazioni di tipo (esempio: typedef float reale;)
– Definisce il binding tra il nome del tipo e l’implementazione
– Eredita tutte le operazioni del tipo specificato
•
Tipi di dati astratti
nome_nuovo_tipo ={
struttura dati degli oggetti del nuovo tipo;
operazioni per manipolare gli oggetti del nuovo tipo;
}
– Associano il nuovo tipo alle operazioni definite
Politecnico di Milano - Prof. Sara Comai
21
Tipizzazione statica e dinamica
• Tipizzazione statica (C/C++, Pascal, ecc.)
– Il binding delle variabili al loro tipo avviene a tempo di
compilazione
– Il binding non può essere cambiato durante l’esecuzione
• Permette la verifica del corretto uso delle variabili a tempo di
compilazione
• Tipizzazione dinamica (LISP, APL, Smalltalk, ecc.)
– Il binding avviene a tempo di esecuzione
– Le variabili sono polimorfiche (il tipo dipende dal valore associato
dinamicamente)
• Non è possibile verificare l’uso corretto delle variabili staticamente
• Linguaggi non tipizzati (linguaggi di script, assemblatori)
– Le variabili non sono tipizzate
– Celle di memoria e registri contengono stringhe che possono
essere interpretate come valori di qualsiasi tipo
Politecnico di Milano - Prof. Sara Comai
22
l-value
variabile = <nome, scope, tipo, l-value, r-value>
•
l-value:
– area di memorizzazione associata ad una variabile durante
l’esecuzione
•
Tempo di vita (lifetime o extent):
– durata di tale binding
•
Allocazione della memoria:
– Allocazione di un’area della memoria ad una variabile
– Il tempo di vita di una variabile va dalla sua allocazione alla sua
disallocazione
• Allocazione statica: prima dell’esecuzione e disallocazione al termine
dell’esecuzione (automaticamente)
• Allocazione dinamica: durante l’esecuzione e disallocazione durante
l’esecuzione (automaticamente o su richiesta)
Politecnico di Milano - Prof. Sara Comai
23
r-value
variabile = <nome, scope, tipo, l-value, r-value>
• r-value:
– Valore codificato memorizzato nella locazione associata alla
variabile (l-value)
• Interpretato a seconda del tipo della variabile
• Istruzioni di un programma
– Accedono alle variabili attraverso l-value (left)
– Modificano r-value (right)
• x=y;
// x indica una locazione, y un valore
• Binding tra una variabile ed il valore:
– Dinamico Æ operazione di assegnamento: x=10;
– Statico Æ costanti simboliche: const int MAX = 10;
Politecnico di Milano - Prof. Sara Comai
24
Inizializzazione di variabili
• Qual è l’r-value di una variabile dopo la sua
creazione?
– In alcuni linguaggi il binding deve essere definito quando la
variabile viene creata (ML)
– Altri lo supportano ma non lo richiedono (C/C++)
• int i=0;
– Se l’inizializzazione non viene specificata la soluzione
adottata dipende dall’implementazione
• Ignorata: considera la stringa nell’area di memoria come valore
iniziale
• Definita dal sistema: es. int inizializzati a 0
• Valore speciale non definito per inizializzare la variabile che
non permette di usare la variabile finchè non viene assegnato
un valore (verifica di correttezza del programma)
Politecnico di Milano - Prof. Sara Comai
25
Reference e variabili senza nome
• Variabili che possono essere accedute tramite l’r-value
di altre variabili
– reference o puntatore alla variabile
• Possono non avere un nome (ma esiste percorso di
accesso)
• Esempio:
int x = 5; //r-value di x è 5
int *px;
px = &x; //r-value di px è 5
Condivisione di oggetti
Accessibili:
•direttamente (x)
•indirettamente (px)
*px = 0;
//r-value di px è 0
int y = *px; //r-value di px è 0
Dereferenziazione:
accesso tramite il
puntatore
Politecnico di Milano - Prof. Sara Comai
26
Informatica 3
Lezione 2- Modulo 4
Routine
Convenzioni dei nomi
Politecnico di Milano - Prof. Sara Comai
27
Routine
• Routine: unità di decomposizione di un
programma che implementa un’operazione
astratta
– Assembler: sottoprogramma
– C: funzione
– Pascal: procedure e funzioni
• Procedure: non restituiscono valori
• Funzioni: restituiscono valori
Politecnico di Milano - Prof. Sara Comai
28
Oggetti di una routine
Routine = <nome, scope, tipo, l-value, r-value>
– Il nome della routine può essere introdotto tramite
la dichiarazione della routine
• int sum(int n); //prototipo C
– Lo scope va dalla dichiarazione ad un punto di
chiusura (C: fine del file che contiene la
dichiarazione)
• L’attivazione di una routine avviene tramite
l’invocazione o chiamata della routine
– Dev’essere nello scope della routine
– Specifica il nome della routine ed i parametri
Politecnico di Milano - Prof. Sara Comai
29
Oggetti di una routine
• La routine definisce lo scope per le dichiarazioni in
essa annidate
– Dichiarazioni locali (visibili solo dalla routine)
– Non locali (visibili da altre unità)
– Globali (visibili da tutte le unità del programma)
Routine = <nome, scope, tipo, l-value, r-value>
• Il tipo della routine è definito dalla sua intestazione
– Signature: tipi dei parametri di input e tipo restituito
• int funzione(int, int, float)
– Una chiamata di una routine è corretta se è conforme al suo
tipo
Politecnico di Milano - Prof. Sara Comai
30
l-value e r-value
Routine = <nome, scope, tipo, l-value, r-value>
• l-value: area di memoria che contiene il corpo della
routine
• r-value: corpo della routine correntemente associato
tramite binding
– Normalmente è statico, definito a tempo di traduzione
– Alcuni linguaggi supportano un binding dinamico:
• Variabili di tipo routine a cui si può assegnare una routine
• Es. linguaggio C
int sum(int);
int (*ps)(int);
ps=∑
Æ int i = (*ps)(5);
• Routine come “first-class objects”
Politecnico di Milano - Prof. Sara Comai
31
Dichiarazione e definizione
• Dichiarazione: intestazione della routine
– Definisce lo scope
• Definizione: intestazione e corpo della routine
• La distinzione serve per poter avere mutua ricorsione
– Esempio:
int funzA (int x);
float funzB (int y){
…
z=funzA (y);
…
}
//dichiarazione
//definizione
//chiamata di funzione (visibile!)
Politecnico di Milano - Prof. Sara Comai
32
Parametri della routine
• Per passaggio informazioni
– Oggetti di dati
– Routine (in alcuni linguaggi)
• Parametri
– Formali: parametri che appaiono nella definizione
– Attuali: parametri che appaiono nella chiamata alla
routine
• Binding
– Secondo il metodo posizionale
Routine: R(F1,F2,…,Fn);
Chiamata: R(A1,A2,…,An);
– Tramite associazione del nome
Routine: R(A:T1; B:T2; C:T3);
Chiamata: R(C=>Z, A=>X, B=>Y);
Politecnico di Milano - Prof. Sara Comai
33
Routine generiche
• Esempio:
– Routine per ordinare array di interi
• … int i,j; … swap(i,j);
//caso 1
– Routine per ordinare array di float
• … float i,j; … swap(i,j); //caso 2
• Template con tipo generico in C++:
template <class T> void swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
– Nel caso 1 viene istanziata una routine con interi,
– nel caso 2 una routine con float
• I parametri generici vengono associati tramite binding
ai parametri attuali a tempo di compilazione
Politecnico di Milano - Prof. Sara Comai
34
Overloading
int i,j,k;
float a,b,c;
…
i=j+k;
a=b+c;
a=b+c+b();
Æb variabile
Æb() funzione
Operatore +
Æ Somma tra interi
a=b()+c+b(i);
Æb() e b(int)
funzioni distinte
Æ Somma tra float
Overloading: la stessa entità viene utilizzata con
significati diversi.
• Il binding per l’entità viene stabilito a tempo di
compilazione in base alle informazioni disponibili
– Esempio: per l’operatore + il binding con la corrispondente
operazioni viene stabilito in base al tipo dei parametri
Politecnico di Milano - Prof. Sara Comai
35
Aliasing
Aliasing: contrario di overloading
• Due nomi sono alias se denotano la stessa entità
nello stesso punto del programma
int x;
int *y=&x;
x e *y rappresentano
la stessa variabile
int q1 (int a)
{
return a*= a;
}
int x=2;
void q2 (int &a)
{
a *= a;
}
i e a rappresentano la
stessa variabile
cout << q1(x); cout << x; // stampa 4 e 2
q2(x); cout << x;
Politecnico di Milano - Prof. Sara Comai
// stampa 4
36