Skip to content

Commit d797a98

Browse files
Merge pull request #109 from filippodaniotti/errata-corrige-1.0.0
Errata Corrige v1.0.0
2 parents b9cd980 + 27f40b2 commit d797a98

File tree

26 files changed

+439
-394
lines changed

26 files changed

+439
-394
lines changed

src/chapters/01/chapter01.tex

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ \subsection{Cos'è un compilatore}
2222

2323
\subsection{Le fasi del processo di compilazione}
2424
In questa sezione presentiamo le fasi del processo di compilazione come se fossero in pipeline, ma sappi che per ragioni di efficienza vengono spesso sovrapposte. Due punti fondamentali di questo processo sono i seguenti:
25-
\begin{enumerate}
26-
\item Se scriviamo il programma in un certo linguaggio, lo dovremo compilare con il compilatore dedicato esattamente a quel linguaggio
27-
\item Quando scrivo codice per un certo compilatore devo rispettare la grammatica del linguaggio per cui il compilatore lavora
28-
\end{enumerate}
25+
\begin{itemize}
26+
\item se scriviamo il programma in un certo linguaggio, lo dovremo compilare con il compilatore dedicato esattamente a quel linguaggio;
27+
\item quando scrivo codice per un certo compilatore devo rispettare la grammatica del linguaggio per cui il compilatore lavora.
28+
\end{itemize}
2929
La grammatica di un linguaggio definisce la struttura legale delle varie operazioni possibili in quel linguaggio; ad esempio, può definire questa forma per un’operazione di assegnamento:
3030
\begin{equation*}
3131
\textrm{\texttt{Identifier Assign Expression Semicolon}}
@@ -36,15 +36,15 @@ \subsection{Le fasi del processo di compilazione}
3636
Avendo chiarito il punto di partenza, possiamo procedere con una descrizione delle fasi della compilazione.
3737

3838
\subsubsection{Analisi lessicale}
39-
Il primo passaggio che compie il compilatore è l’analisi lessicale: questa traduce un flusso di caratteri in un flusso di \emph{tokens}, ciò significa che risolve ogni “stringa” riconoscendo il suo ruolo. Per esempio, traduce:
39+
Il primo passaggio che compie il compilatore è l’analisi lessicale: questa traduce un flusso di caratteri in un flusso di \emph{tokens}, vale a dire che risolve ogni statement, riconoscendo il ruolo degli elementi che lo compongono e ritornandone una nuova stringa processata. Per esempio, traduce questa linea:
4040
\begin{equation*}
41-
\textrm{\texttt{pippo = 2*3}}
41+
\textrm{\texttt{pippo = 2*3;}}
4242
\end{equation*}
43-
In una nuova stringa, che ha una forma simile a:
43+
In una nuova linea che descrive la funzione dei vari elementi, qualcosa di simile a:
4444
\begin{equation*}
4545
\textrm{\texttt{<ID, pippo> ASS <NUM,2 > MUL <NUM,3> SEMCOL}}
4646
\end{equation*}
47-
In questa fase i token che otteniamo contengono le informazioni sul tipo di dato o comando che ogni singola stringa identifica, “si tratta di capire chi è chi”. Nota che non vengono perse informazioni, non si tratta di una traduzione in cui la stringa dell’ID viene eliminata: si tiene la stringa pippo e vi si assegna il ruolo di identificatore (ID).
47+
In questa fase è sufficiente dire che i token che otteniamo contengono le informazioni sul tipo di dato o comando che ogni singola stringa identifica. Nota che non vengono perse informazioni, non si tratta di una traduzione in cui la stringa dell’ID viene eliminata: si tiene la stringa \texttt{pippo} e vi si assegna il ruolo di identificatore (ID).
4848

4949
\subsubsection{Analisi sintattica}
5050
Dopo l’analisi lessicale arriva l’analisi sintattica: questa analisi verifica che la sequenza di token sia aderente alla grammatica del linguaggio che stiamo utilizzando, ed è la fase in cui compaiono i temuti syntax error.
@@ -63,11 +63,11 @@ \subsubsection{Analisi sintattica}
6363
\centering
6464
\subimport{assets/figures/}{abstract-syntax-tree.tex}
6565
\caption{Esempio di abstract syntax tree}
66-
\label{esempio_AST}
66+
\label{esempioAST}
6767
\end{figure}
6868
Il guadagno in complessità in questo caso è poco (abbiamo risparmiato tipo 3 nodi), ma in casi più complessi il risparmio è molto più rilevante.
6969
\paragraph*{}
70-
Non è facile scrivere una grammatica che possa essere analizzata con efficienza da un compilatore e che, al tempo stesso, generi parse tree più semplici possibili; ma di questo discuteremo in futuro. È da notare che esistono svariate forme di compilatori, noi ne stiamo vedendo una presentazione generale, ma, in molti casi, fasi come creazione di parse tree e AST vengono spesso sovrapposte.
70+
Non è facile scrivere una grammatica che possa essere analizzata con efficienza da un compilatore e che, al tempo stesso, generi parse tree più semplici possibili; ma di questo discuteremo in futuro. È da notare che esistono svariate forme di compilatori, noi ne stiamo vedendo una presentazione generale, ma, in molti casi, fasi come creazione di parse tree e AST vengono spesso parallelizzate.
7171
\paragraph{}
7272
L’output dell’analisi sintattica è chiamato \emph{tree}, ma non necessariamente è un albero: spesso può essere un grafo. Ad esempio in un’operazione del tipo:
7373
\texttt{pippo = pippo * 2}
@@ -76,19 +76,18 @@ \subsubsection{Analisi sintattica}
7676
\centering
7777
\subimport{assets/figures/}{pippo-tree.tex}
7878
\caption{Abstract syntax tree che diventa un grafo quando la variabile a cui si assegna il valore fa parte dell'espressione alla destra dell'assegnamento.}
79-
\label{esempio_pippo}
8079
\end{figure}
8180

8281
\subsubsection{Analisi semantica}
83-
Ora è la fase dell’analisi semantica. Un esempio di operazione di analisi semantica è quello di capire se stiamo utilizzando il giusto operatore di moltiplicazione per l’operazione che vogliamo effettuare. Stiamo chiaramente riferendoci a quei linguaggi in cui esistono diversi significati per uno stesso operatore, come nel caso in cui l'operatore \texttt{MUL} può significare moltiplicazione sia tra interi sia tra float. Quindi si può dire che in questo caso l’analisi semantica chiarisce quale significato ha l’operatore \texttt{MUL}: nell’esempio riportato in \ref{esempio_AST} \texttt{MUL} = moltiplicazione tra due variabili di tipo \texttt{NUM}.
82+
Ora è la fase dell’analisi semantica. Un esempio di operazione di analisi semantica è quello di capire se stiamo utilizzando il giusto operatore di moltiplicazione per l’operazione che vogliamo effettuare. Stiamo chiaramente riferendoci a quei linguaggi in cui esistono diversi significati per uno stesso operatore, come nel caso in cui l'operatore \texttt{MUL} può significare moltiplicazione sia tra interi sia tra float. Quindi si può dire che in questo caso l’analisi semantica chiarisce quale significato ha l’operatore \texttt{MUL}: nell’esempio riportato in \ref{esempioAST} \texttt{MUL} = moltiplicazione tra due variabili di tipo \texttt{NUM}.
8483
\begin{figure}[H]
8584
\centering
8685
\subimport{assets/figures/}{semantica-mul.tex}
8786
\caption{La semantica di \texttt{MUL} deve essere specificata}
8887
\end{figure}
8988

9089
\subsubsection{Generazione del codice intermedio}
91-
È il momento della generazione del codice intermedio: in questa fase viene creato un codice testuale creato traducendo il parse tree. Queste istruzioni sono leggibili dall’uomo ma non è né assembly né codice effettivo, d’altronde si chiama intermedio, no? Nell'esempio in \ref{codice_intermedio} abbiamo sulla sinistra il parse tree e sulla destra abbiamo un esempio del codice intermedio generato.
90+
È il momento della generazione del codice intermedio: in questa fase viene generato un codice testuale traducendo il parse tree. Queste istruzioni sono leggibili dall’uomo ma non è né assembly né codice effettivo, d’altronde si chiama intermedio, no? Nell'esempio in \ref{codice_intermedio} abbiamo sulla sinistra il parse tree e sulla destra abbiamo un esempio del codice intermedio generato.
9291
\begin{figure}[H]
9392
\begin{minipage}{.5\textwidth}
9493
\raggedleft
@@ -121,8 +120,8 @@ \section{Riassumendo le fasi della compilazione}
121120
\end{enumerate}
122121
Possiamo dividere questi passaggi in due gruppi:
123122
\begin{itemize}[]
124-
\item \emph{Front-end} Dall’analisi lessicale fino al codice intermedio.
125-
\item \emph{Back-end} Tutto il resto.
123+
\item \emph{Front-end}: dall’analisi lessicale fino al codice intermedio.
124+
\item \emph{Back-end}: tutto il resto.
126125
\end{itemize}
127126
Ma perché passiamo dalla fase del codice intermedio? Per ragioni di modularità:
128127
Se abbiamo \(N\) linguaggi, abbiamo \(N\) front-end e se abbiamo \(K\) macchine, abbiamo \(K\) back-end ciò implica che senza un codice intermedio dovremo creare \(N*K\) differenti compilatori, usiamo il codice intermedio come livello di astrazione per semplificare il tutto.

0 commit comments

Comments
 (0)