Skip to content

Sintassi

La sintassi si occupa di controllare se una stringa è legale (ovvero rispetta le regole della grammatica)

Ogni elemento (o carattere) del codice di un programma è un simbolo e fa parte della sintassi.
La sematica (non la sintassi) si occupa di "dare" il significato ad ogni simbolo.
La sintassi è quindi la struttura dei costrutti di cui il linguaggio di programmazione farà uso.

La sintassi si basa sul lessico, e ci permette quindi di effettuare due operazioni:

  • Analisi Lessicografica (controllare che i termini siano validi)
  • Grammatiche (tutte le frasi legali che posso esprimere nel linguaggio che sto definendo)
    Ci permette quindi di:
    • Definire un linguaggio durante la fase di creazione
    • Leggere e studiare un nuovo linguaggio in fase di apprendimento

Definizione di Alfabeto

Insieme finito e non vuoto di simboli o caratteri

Definizione di lessico

Insieme delle parole del linguaggio composte a partire da un insieme di simboli atomici detti caratteri che rappresentano l'alfabeto del linguaggio.
Le parole saranno poi utilizzate per formare frasi esprimibili in quel linguaggio

Definizione di parola legale

Le parole legali sono un sottoinsieme di tutte le parole che si possono costruire.
Una parola legale sarà quindi una parola appartenente a questo sottoinsieme

Definizione di stringa

Una stringa è il risultato della concatenazione di elementi di un insieme (finito o vuoto) di simboli (un alfabeto)

Linguaggio di Programmazione

un linguaggio di programmazione è l'insieme delle stringhe ammissibili, che prendono il nome di programmi.

ASCII è un alfabeto. La maggior parte dei linguaggi si basa su un sottoinsieme di questo alfabeto (insieme riferito come "printable characters" o caratteri stampabili, come quelli di cui è composta questa pagina)

Operazioni sui caratteri

Concatenazione

Operazione definita sui simboli di un alfabeto: \(\forall a,b \in A . a \cdot b = b a\)

Esponenziale

Dato \(x^0 = \epsilon\) (dove \(\epsilon\) = stringa vuota), \(x^n = x \cdot x^{n-1}\)

Prefisso

Stringa con uno scarto della coda

Suffisso

Stringa con uno scarto dalla testa

Sottostringa

Stringa senza prefisso e suffisso (prefisso e suffisso risultano cancellati)

Lunghezza di una stringa

Si indica con i trattini verticali (che richiamano alla cardinalità) ed indicano il numero di elementi dell'alfabeto nella stringa:
\(|ciao| = 4\)

Chiusura di Kleene *

Insieme di simboli contenente tutte le stringhe di tutte le lunghezze (0(\(\epsilon\)),1,2,3,...) formabili concatenando un alfabeto

Chiusura positiva +

Una chiusura positiva è una chiusura di Kleene con lunghezza > 0
Ci permette di identificare un insieme non vuoto di tutte le stringhe possibili ottenibili concatenando un alfabeto.

Linguaggi

Linguaggio

Un linguaggio è un sottoinsieme della chiusura positiva dell'alfabeto
È l'insieme delle stringhe ammissibili (chiamati programmi)

Linguaggio infinito

Definibile attraverso 3 metodi ed è definibile enumerando tutti i suoi elementi (ove non infiniti)

Un linguaggio L su un alfabeto A è un sottoinsieme della chiusura di Kleene (considerando insiemi non vuoti e non banali) Un linguaggio di programmazione classico può essere pensato come un sottoinsieme di ASCII*

Generativo

Insieme delle stringhe generate (che seguono le regole) da una grammatica

Riconoscitivo

Insieme delle stringhe riconosciute ad un automa

Algebrico

Insieme delle stringhe soluzione di un sistema di equazioni algebriche

Albero di derivazione

L'albero di derivazione è un albero radicato non vuoto in cui:

  • La radice è etichettata con il simbolo iniziale
  • Ogni nodo interno è etichettato con un simbolo non terminale e rappresenta l'applicazione di una produzione
  • Ogni foglia è etichettata con un simbolo terminale

La stringa corrispondente ad un albero (di derivazione) si ottiene dalla frontiera, concatenando le etichette delle foglie da sinistra a destra

Ogni sotto albero risulta essere l'applicazione di una produzione
Ad ogni albero sono associate più derivazioni, a seconda dell'ordine in cui vengono applicate le derivazioni.

Esiste una corrispondenza biunivoca tra alberi di derivazione e derivazioni canoniche: se derivo sempre da destra (o sinistra), ottengo sempre lo stesso albero.
Ciò significa che se derivo sempre da destra (o sinistra) ottengo sempre lo stesso albero.

Grammatica ambigua

Lo stesso linguaggio si può ottenere con 2 alberi diversi (ovvero, ci può essere indecisione su quale può essere l'albero da usare). La produzione non riesce a determinare una precedenza con gli operatori (questo perché dal punto di vista della sintassi tutti i simboli hanno uguale precedenza, non abbiamo ancora inserito una semantica che ci permette di attribuire un significato degli operatori (come addizione e moltiplicazione) e quindi una precedenza).
Ciò porta il parser a decidere arbitrariamente l'ordine degli operatori, prima di passare all'organizzatore semantico (che poi è in grado di assegnare un significato ai simboli)

La soluzione a questo problema (disambiguazione) è data dall'aggiunta di operatori per non permettere alla scelta di poter esistere in primo luogo.
Questo perché l'analizzatore sintattico (parser) usa grammatiche non ambigue per determinare la precedenza tra operatori. Se così non fosse, potrebbero verificarsi "undefined behavior"

Albero di sintassi astratta

Un albero di sintassi risulta essere una versione compatta dell'albero di derivazione, perché imporre la precedenza aumenta il numero di produzioni.
Per ottimizzare quindi si mantiene la non ambiguità, rimuovendo però tutti i nodi interni non terminali che non sono direttamente collegati a foglie.

Esempio di albero di sintassi

prendendo come regole scritte in BNF le seguenti produzioni:
\(E ::= E + T | T\)
\(T ::= T \star F | F\)
\(F ::= a | b | c | (E)\)

Possiamo prendere la stringa \(a \star (b + c)\) ed effettuare una trasformazione delle produzioni partendo da E come simbolo iniziale:
\(E \to T \to T \star F \to T \star (E) \to T \star (E+T) \to T \star (E+F) \to T \star (E+c) \to\)
\(\to T \star (T+c) \to T \star (F+c) \to T \star (b+c) \to F \star (b+c) \to a \star (b+c)\)

Albero di sintassi

In questo esempio la frontiera sono i nodi a, *, b, +, c


Categorie sintattiche
Dichiarazioni
Comandi
Espressioni
Lessico
Grammatica
Back to top