Informatica 3 Informatica 3 LEZIONE 2: Sintassi e semantica Lezione 2- Modulo 1 • Modulo 1: Introduzione ai concetti di sintassi e semantica • Modulo 2: Il concetto di binding • Modulo 3: Variabili • Modulo 4: Routine – Convenzioni dei nomi Introduzione ai concetti di sintassi e semantica Politecnico di Milano - Prof. Sara Comai 1 Le componenti di un linguaggio di programmazione 2 Sintassi di un linguaggio • Un linguaggio di programmazione è una notazione formale caratterizzata da due componenti: • Sintassi: regole che definiscono le sequenze valide di simboli – Frasi come sequenze di parole – Parole: definite su un alfabeto – Sintassi: insieme di regole formali che specificano la composizione di programmi • Regole lessicali: insieme di caratteri che costituiscono l’alfabeto del linguaggio • Per determinare se un programma è valido – Semantica: insieme di regole che specificano il “significato” di un programma sintatticamente valido – Esempi: • Caratteri maiuscoli e minuscoli differiscono in C/C++ ma sono identici in Pascal • L’operatore “diverso” è: != in C/C++ e <> in Pascal • 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 Politecnico di Milano - Prof. Sara Comai 3 Politecnico di Milano - Prof. Sara Comai 4 1 EBNF – regole sintattiche EBNF=Extended Backus Naur Form Metalinguaggio con metasimboli ::= < > | * + • Regole sintattiche: non terminale terminale EBNF – regole lessicali • Regole lessicali: 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 <operatore> <identificatore> <ld> <numero> <lettera> <cifra> 5 Diagrammi sintattici condizione { } assegnamento ciclo while istruzione } else { istruzione } espressione { istruzione } condizione ciclo assegnamento { espressione if istruzione istruzione 6 Politecnico di Milano - Prof. Sara Comai Diagrammi sintattici programma ::= + | - | * | / | = | /= | < | > | <= | >= ::= <lettera> <ld>* ::= <lettera> | <cifra> ::= <cifra>+ ::= a | b | c | . . . | z ::= 0 | 1 | . . . | 9 espressione espressione operatore espressione identificatore identificatore = espressione numero { Politecnico di Milano - Prof. Sara Comai 7 espressione } Politecnico di Milano - Prof. Sara Comai 8 2 Sintassi astratta e concreta Sintassi concreta e usabilità • Costrutti in linguaggi diversi possono avere la stessa struttura concettuale, ma avere regole lessicali diverse: while (x!=y) { … } • <> è più leggibile di != • Se il ciclo contiene una singola istruzione le { } possono essere omesse while x<>y do begin … end – Facile commettere errori!! while (num!=0){ cin >> num; } – Stessa sintassi astratta – Diversa sintassi concreta Politecnico di Milano - Prof. Sara Comai while (num!=0) cin >> num; while num <> 0 do … end 9 Politecnico di Milano - Prof. Sara Comai 10 Il concetto di binding Informatica 3 • I programmi sono costituiti da entità – variabili, routine, istruzioni • Le entità sono caratterizzate da attributi Lezione 2- Modulo 2 – Variabile: nome, tipo, area di memoria – Routine: nome, parametri, modalità di passaggio parametri Il concetto di binding • Binding: associa un valore agli attributi • Per ogni entità le informazioni sulle entità sono contenute in un descrittore Politecnico di Milano - Prof. Sara Comai 11 Politecnico di Milano - Prof. Sara Comai 12 3 Binding Linguaggi e binding • Binding definito dalla definizione del linguaggio: • Concetto fondamentale nella definizione della semantica di un linguaggio – Esempio: interi Æ insieme di operazioni eseguibili (Fortran, Ada, C, C++) – Linguaggi diversi presentano • Binding definito dall’implementazione del linguaggio: • 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) – 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 statico: non può essere modificato – Binding dinamico: modificabile durante l’esecuzione Binding dinamico Politecnico di Milano - Prof. Sara Comai 13 Politecnico di Milano - Prof. Sara Comai 14 Variabili Informatica 3 • 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 Lezione 2- Modulo 3 Variabili – 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 15 Politecnico di Milano - Prof. Sara Comai 16 4 Nome e regole di visibilità Nome e regole di visibilità • Le regole di binding di una variabile all’interno del suo scope dipendono dal linguaggio variabile = <nome, scope, tipo, l-value, r-value> • Nome: stringa di caratteri che denota la variabile – Binding statico dello scope – Solitamente introdotto tramite una dichiarazione • Lo scope viene definito staticamente, tramite una dichiarazione implicita o esplicita, senza dover eseguire il programma • Maggior parte di linguaggi di programmazione (C/C++) • 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 – Binding dinamico dello scope 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 • Lo scope viene definito durante l’esecuzione del programma • APL, vecchi LISP, SNOBOL4 17 Esempio di binding dinamico dello scope variabile = <nome, scope, tipo, l-value, r-value> Esempio: A Æ C; B Æ C • Tipo di una variabile: } { /* blocco B */ int x; – insieme di valori che possono essere associati alla variabile •Regole semplici da implementare + •Implementazione meno efficiente } { /* blocco C */ x = ...; } 18 Tipo { /* blocco A */ int x; Politecnico di Milano - Prof. Sara Comai – operazioni per creare, accedere, modificare tali valori •Programmi difficili da leggere Politecnico di Milano - Prof. Sara Comai 19 Politecnico di Milano - Prof. Sara Comai 20 5 Tipi e binding Tipizzazione statica e dinamica • Tipizzazione statica (C/C++, Pascal, ecc.) • 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 – 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 • Dichiarazioni di tipo (esempio: typedef float reale;) • Tipizzazione dinamica (LISP, APL, Smalltalk, ecc.) – Definisce il binding tra il nome del tipo e l’implementazione – Eredita tutte le operazioni del tipo specificato – Il binding avviene a tempo di esecuzione – Le variabili sono polimorfiche (il tipo dipende dal valore associato dinamicamente) • Tipi di dati astratti • Non è possibile verificare l’uso corretto delle variabili staticamente nome_nuovo_tipo ={ struttura dati degli oggetti del nuovo tipo; operazioni per manipolare gli oggetti del nuovo tipo; } • 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 – Associano il nuovo tipo alle operazioni definite Politecnico di Milano - Prof. Sara Comai 21 Politecnico di Milano - Prof. Sara Comai l-value r-value variabile = <nome, scope, tipo, l-value, r-value> variabile = <nome, scope, tipo, l-value, r-value> • l-value: • r-value: – area di memorizzazione associata ad una variabile durante l’esecuzione – Valore codificato memorizzato nella locazione associata alla variabile (l-value) • Tempo di vita (lifetime o extent): • Interpretato a seconda del tipo della variabile – durata di tale binding • Istruzioni di un programma – Accedono alle variabili attraverso l-value (left) – Modificano r-value (right) • 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 • x=y; // x indica una locazione, y un valore • Binding tra una variabile ed il valore: • 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 22 – Dinamico Æ operazione di assegnamento: x=10; – Statico Æ costanti simboliche: const int MAX = 10; 23 Politecnico di Milano - Prof. Sara Comai 24 6 Inizializzazione di variabili Reference e variabili senza nome • Qual è l’r-value di una variabile dopo la sua creazione? • Variabili che possono essere accedute tramite l’r-value di altre variabili – In alcuni linguaggi il binding deve essere definito quando la variabile viene creata (ML) – Altri lo supportano ma non lo richiedono (C/C++) – reference o puntatore alla variabile • Possono non avere un nome (ma esiste percorso di accesso) • Esempio: • 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 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 Routine Informatica 3 • Routine: unità di decomposizione di un programma che implementa un’operazione astratta Lezione 2- Modulo 4 – Assembler: sottoprogramma – C: funzione – Pascal: procedure e funzioni Routine Convenzioni dei nomi Politecnico di Milano - Prof. Sara Comai int x = 5; //r-value di x è 5 int *px; px = &x; //r-value di px è 5 • Procedure: non restituiscono valori • Funzioni: restituiscono valori 27 Politecnico di Milano - Prof. Sara Comai 28 7 Oggetti di una routine Oggetti di una routine • La routine definisce lo scope per le dichiarazioni in essa annidate Routine = <nome, scope, tipo, l-value, r-value> – Dichiarazioni locali (visibili solo dalla routine) – Non locali (visibili da altre unità) – Globali (visibili da tutte le unità del programma) – 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 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 – Dev’essere nello scope della routine – Specifica il nome della routine ed i parametri Politecnico di Milano - Prof. Sara Comai 29 l-value e r-value Politecnico di Milano - Prof. Sara Comai 30 Dichiarazione e definizione Routine = <nome, scope, tipo, l-value, r-value> • Dichiarazione: intestazione della routine – Definisce lo scope • l-value: area di memoria che contiene il corpo della routine • r-value: corpo della routine correntemente associato tramite binding • 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); … } – Normalmente è statico, definito a tempo di compilazione – 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 //definizione //chiamata di funzione (visibile!) Politecnico di Milano - Prof. Sara Comai 32 8 Parametri della routine Routine generiche • Esempio: • Per passaggio informazioni – Routine per ordinare array di interi – Oggetti di dati – Routine (in alcuni linguaggi) • … int i,j; … swap(i,j); • … float i,j; … swap(i,j); //caso 2 • Parametri • Template con tipo generico in C++: – Formali: parametri che appaiono nella definizione – Attuali: parametri che appaiono nella chiamata alla routine template <class T> void swap(T& a, T& b) { T temp = a; a = b; b = temp; } • 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); – 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 33 Politecnico di Milano - Prof. Sara Comai a=b+c+b(); 34 Politecnico di Milano - Prof. Sara Comai Overloading int i,j,k; float a,b,c; … i=j+k; a=b+c; //caso 1 – Routine per ordinare array di float Aliasing Æb variabile Æb() funzione Aliasing: contrario di overloading • Due nomi sono alias se denotano la stessa entità nello stesso punto del programma 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 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 9