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=&sum; Æ 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