Il 0% ha trovato utile questo documento (0 voti)
5 visualizzazioni48 pagine

Linguaggi e Compilatori: Corso Di Laurea in Informatica

Il documento tratta della generazione dell'Abstract Syntax Tree (AST) per il front-end di Kaleidoscope 1.0, evidenziando l'importanza di un'architettura modulare per la progettazione e programmazione. Viene descritto il funzionamento dei moduli coinvolti, tra cui scanner e parser, e la loro interazione attraverso una classe driver che gestisce il contesto di parsing. Inoltre, si esplorano le rappresentazioni astratte di programmi e strutture di controllo tramite l'AST, fornendo esempi pratici di come queste strutture possano essere rappresentate.

Caricato da

alefranco41
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
5 visualizzazioni48 pagine

Linguaggi e Compilatori: Corso Di Laurea in Informatica

Il documento tratta della generazione dell'Abstract Syntax Tree (AST) per il front-end di Kaleidoscope 1.0, evidenziando l'importanza di un'architettura modulare per la progettazione e programmazione. Viene descritto il funzionamento dei moduli coinvolti, tra cui scanner e parser, e la loro interazione attraverso una classe driver che gestisce il contesto di parsing. Inoltre, si esplorano le rappresentazioni astratte di programmi e strutture di controllo tramite l'AST, fornendo esempi pratici di come queste strutture possano essere rappresentate.

Caricato da

alefranco41
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd

Linguaggi e compilatori

Corso di Laurea in Informatica

Mauro Leoncini

A.A. 2023/2024

Mauro Leoncini L&C Anno Accademico 2023/24 1 / 48


Linguaggi e compilatori

1 Generazione dell'AST
Architettura del front-end
Rappresentazione astratta di un programma
Verso l'ASD di Kaleidoscope 1.0

Mauro Leoncini L&C Anno Accademico 2023/24 2 / 48


Generazione dell'AST Architettura del front-end

Linguaggi e compilatori

1 Generazione dell'AST
Architettura del front-end
Rappresentazione astratta di un programma
Verso l'ASD di Kaleidoscope 1.0

Mauro Leoncini L&C Anno Accademico 2023/24 3 / 48


Generazione dell'AST Architettura del front-end

Organizzazione modulare

Il nostro obiettivo è progettare (e programmare) un front-end per la


prima versione di Kaleidoscope (che per comodità chiameremo
Kaleidoscope 1.0 )
L'output desiderato per il frot-end è, al momento, solo l' Abstract
Syntax Tree (AST) del programma in input

Iniziamo con delineare la struttura dell'applicazione

Potremmo scrivere tutto in due sole unità di programma: lo scanner e


il parser, includendo in quest'ultimo un main program che coordini
tutte le attività

Proponiamo invece una soluzione modulare, più facilmente


comprensibile, manutenibile e debuggabile

La stessa architettura modulare costituisce da sola una migliore


documentazione dell'applicazione

Mauro Leoncini L&C Anno Accademico 2023/24 4 / 48


Generazione dell'AST Architettura del front-end

I moduli dell'applicazione

L'applicazione consta dunque dei seguenti moduli

Un modulo scanner per la lettura del le e l'analisi lessicale, generato


utilizzando Flex
Un modulo per il parsing e la costruzione dell'AST, generato
utilizzando Bison

Un modulo driver, che include tutte le classi C++ di cui i nodi


dell'AST costituiscono istanze

Il modulo driver denisce anche una classe (omonima) che rappresenta


il c.d. parsing context, ovvero una struttura dati che consente
un'ecace condivisione di dati fra parser e scanner (e main program)
prescindendo dall'uso di variabili globali

Un client che include il main program e il cui compito è di eettuare il


parsing dei parametri forniti dall'utilizzatore nella riga di comandi e di
lanciare la compilazione

Mauro Leoncini L&C Anno Accademico 2023/24 5 / 48


Generazione dell'AST Architettura del front-end

Il programma client

#include <iostream>
#include "[Link]"

int main (int argc, char *argv[])


{ driver drv;
for (int i = 1; i < argc; ++i)
if (argv[i] == std::string ("-p"))
drv.trace_parsing = true;
else if (argv[i] == std::string ("-s"))
drv.trace_scanning = true;
else if (![Link] (argv[i])) {
[Link]->visit();
std::cout << std::endl;
} else return 1;
return 0;
}
Mauro Leoncini L&C Anno Accademico 2023/24 6 / 48
Generazione dell'AST Architettura del front-end

Il client e l'uso della classe driver

Come si vede, l'architettura modulare consente di avere un client


molto semplice

A parte le ovvie operazioni di parsing della linea di comando, dal codice


presentato si può iniziare a comprendere l'uso della classe driver
In due opportune variabili della classe, trace_scanning e
trace_parsing, il driver inserisce informazioni che saranno utlizzate
dallo scanner e (indirettamente) dal parser
Un metodo della classe (parse) consente di dare inizio al processo di
compilazione
A ne compilazione, la variabile root contiene la radice dell'AST, da
cui deve iniziare il processo di visita

Le prossime due slide riportano la denizione della classe driver;


quelle immediatamente seguenti mostrano invece gracamente
l'architettura generale

Mauro Leoncini L&C Anno Accademico 2023/24 7 / 48


Generazione dell'AST Architettura del front-end

La classe driver: denizione

class driver {
public:
driver();
void scan_begin(); // Implementata nello scanner
void scan_end(); // Implementata nello scanner
int parse (const std::string& f);

RootAST* root; // Radice dell'AST costruito


yy::location location; //
std::string file; // File sorgente

bool trace_parsing; // Per trace debug nel parser


bool trace_scanning; // Per trace debug nello scanner
};

Mauro Leoncini L&C Anno Accademico 2023/24 8 / 48


Generazione dell'AST Architettura del front-end

La classe driver: implementazione (parziale)

driver::driver(): trace_parsing (false),


trace_scanning (false) {};

int driver::parse (const std::string &f) {


file = f;
[Link](&file);
scan_begin();
yy::parser parser(*this);
parser.set_debug_level(trace_parsing);
int res = [Link]();
scan_end();
return res;
}

Mauro Leoncini L&C Anno Accademico 2023/24 9 / 48


Generazione dell'AST Architettura del front-end

File coinvolti

[Link]
[Link]

definisce
definisce

classi *AST classe driver [Link]

implementa
implementa

[Link]

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 10 / 48


Generazione dell'AST Architettura del front-end

Compilazione di Lexer e Parser

[Link]
[Link]

definisce
[Link]
definisce genera

classi *AST classe driver [Link]


genera
implementa
implementa
[Link]
[Link]
include

[Link]
genera

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 11 / 48


Generazione dell'AST Architettura del front-end

Dopo la compilazione

[Link]
[Link]

definisce
[Link]
definisce

classi *AST classe driver

implementa
implementa
[Link]
[Link]

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 12 / 48


Generazione dell'AST Architettura del front-end

Dipendenze

[Link]
[Link] include

definisce
[Link]
definisce

classi *AST classe driver

implementa
implementa
[Link]
[Link]
include

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 13 / 48


Generazione dell'AST Architettura del front-end

Dipendenze

include [Link]
[Link]

definisce
[Link]
definisce

classi *AST classe driver

implementa
implementa
[Link]
[Link]

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 14 / 48


Generazione dell'AST Architettura del front-end

Esistenza di una dipendenza circolare

Le prossime due slide mostrano l'esistenza di una mutua dipendenza di


driver e parser
Per un verso, infatti, il parser necessita di includere [Link]
Questa è la dipendenza più evidente perché il driver include le classi
*AST (che il parser deve usare per costruire l'albero sintattico) e la
classe driver che funge da contesto

Tuttavia, anche il driver necessita di includere [Link]:


perché è nel parser che è denita la classe location e questa classe è
un fondamentale dato da inserire nel contesto
perché la denizione del tipo di ritorno di yylex è una enumerazione
dei vari token name, che sono deniti dal parser
Per risolvere la circolarità, Bison ha la direttiva %code requires, che
consente di inserire forward declaration nell'header le

Mauro Leoncini L&C Anno Accademico 2023/24 15 / 48


Generazione dell'AST Architettura del front-end

Dipendenze

[Link]
[Link] include

definisce
[Link]
definisce

classi *AST classe driver

implementa
implementa
[Link]
[Link]

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 16 / 48


Generazione dell'AST Architettura del front-end

Dipendenze

[Link]
[Link]

definisce
[Link]
definisce

classi *AST classe driver

implementa
implementa
[Link]
[Link]
include

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 17 / 48


Generazione dell'AST Architettura del front-end

Il usso informativo

[Link]

usa
usa [Link]

usa
classe driver
Token
stream

usa
classi *AST
Token
request

[Link]

Mauro Leoncini L&C Anno Accademico 2023/24 18 / 48


Generazione dell'AST Rappresentazione astratta di un programma

Linguaggi e compilatori

1 Generazione dell'AST
Architettura del front-end
Rappresentazione astratta di un programma
Verso l'ASD di Kaleidoscope 1.0

Mauro Leoncini L&C Anno Accademico 2023/24 19 / 48


Generazione dell'AST Rappresentazione astratta di un programma

AST

L' Abstract Syntax Tree (ASD ) di un'espressione è un albero radicato


in cui i nodi interni rappresentano operatori mentre le foglie
rappresentano operandi

Il numero di gli di un nodo interno corrisponde all' arietà (cioè il


numero di operandi) dell'operatore associato a quel nodo interno

L'albero riette in modo naturale la struttura ricorsiva di


un'espressione: come un operatore può avere, come operando,
un'intera sotto-espressione, così il glio di un nodo interno può essere
a sua volta radice di un sotto-albero

La stessa struttura gerarchica impone poi un'ordine alle operazioni al


ne di valutare l'espressione: se un nodo (interno) X è un discendente
di Y, allora l'operazione rappresentata da Y deve essere logicamente
eseguita prima di (quella di) X
L'intera espressione rappresentata da un ASD può infatti essere
valutata mediante una visita dell'albero in ordine posticipato
Mauro Leoncini L&C Anno Accademico 2023/24 20 / 48
Generazione dell'AST Rappresentazione astratta di un programma

Esempio


L'ASD dell'espressione x· 1 + y + 2 · y2 è

· ·

x sqrt 2 exp

+ y 2

1 y

Mauro Leoncini L&C Anno Accademico 2023/24 21 / 48


Generazione dell'AST Rappresentazione astratta di un programma

ASD per strutture programmative

Non solo le espressioni aritmetiche o logiche ma anche le più


importanti strutture di controllo (condizionali, iterazioni determinate e
indeterminate, oltre che assegnamento e sequenza) possono essere
descritte mediante un albero

Ad esempio, la struttura condizionale a due vie:


if ⟨condition⟩ {⟨true section⟩} else {⟨false section⟩}
può essere rappresentata mediante il seguente ASD

if_else

Tc Tts Tf s

dove if_else è un codice che indica il condizionale a due vie mentre


Tc , Ttc e Tf c sono rispettivamente gli ASD per la condizione di
controllo e per le istruzioni della sezioni true e false

Mauro Leoncini L&C Anno Accademico 2023/24 22 / 48


Generazione dell'AST Rappresentazione astratta di un programma

ASD per strutture programmative

Altri due esempi: sequenza e iterazione indeterminata (while)

⟨statement1⟩ ; {⟨rest⟩} while ⟨condition⟩ {⟨body⟩}


; while

Ts Tr Tc Tb

dove Ts indica l'ASD che rappresenta ⟨statement1⟩, Tr l'ASD che


rappresenta tutte le istruzioni che seguono ⟨statement1⟩ (il resto del
programma) e, inne, Tc e Tb sono gli ASD che descrivono la
condizione di controllo del while e il suo body.

Mauro Leoncini L&C Anno Accademico 2023/24 23 / 48


Generazione dell'AST Rappresentazione astratta di un programma

Un semplice esempio completo

L'ASD per il frammento di codice: x=10;


y=1;
while (x>0) {
x = x-1;
y = 2*y;
; }

= ;
id num = while
id num > ;
id num = =
id - id ×
id num id num
Mauro Leoncini L&C Anno Accademico 2023/24 24 / 48
Generazione dell'AST Rappresentazione astratta di un programma

Qualche osservazione

Le foglie del precedente ASD denotano identicatori o valori numerici

Questa è la situazione generale, nel senso che le foglie denotano token


che possiedono un valore lessicale (il token value )
Nella foglia viene memorizzato sia il token name (evidenziato nella
gura) sia tipicamente un puntatore ad una opportuna entry della
symbol table, dove appunto è registrato il valore lessicale del token
Anche se, come chiarito dagli esempi, un ASD può essere costruito
pure per tipici programmi imperativi, la presenza di istruzioni di
controllo del usso di esecuzione rende tuttavia sensibilmente diverso il
processo di interpretazione (rispetto al caso di semplici espressioni)

Una semplice visita in post-ordine non è infatti in generale suciente


per eseguire il programma descritto dall'ASD

Essa è però suciente nel caso in cui l'obiettivo sia di generare codice,
piuttosto che interpretare il programma

Mauro Leoncini L&C Anno Accademico 2023/24 25 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Linguaggi e compilatori

1 Generazione dell'AST
Architettura del front-end
Rappresentazione astratta di un programma
Verso l'ASD di Kaleidoscope 1.0

Mauro Leoncini L&C Anno Accademico 2023/24 26 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La grammatica per il parser di Bison

Ricordiamo che Kaleidoscope 1.0 deve permettere la scrittura di


programmi che includono solo pochi tipi dierenti di istruzioni:
denizioni di funzioni esterne
dichiarazioni di funzioni
espressioni aritmetiche, che costituiscono il body delle funzioni
dichiarate

Un programma può includere un numero arbitrario di tali istruzioni,


separate da punto e virgola

Per kaleidoscope 1.0 abbiamo visto una grammatica adatta al parsing


top-down

Qui riscriviamo la grammatica pensando all'algoritmo di parsing


incluso in Bison, che è di tipo LR

Mauro Leoncini L&C Anno Accademico 2023/24 27 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Grammatica LR Kaleidoscope 1.0

⟨program⟩ ::= ⟨top⟩ ‘; ‘ ⟨program⟩ | ϵ


⟨top⟩ ::= ⟨def⟩ | ⟨external⟩ | ⟨expr⟩ | ϵ
⟨def⟩ ::= def ⟨proto⟩⟨expr⟩
⟨external⟩ ::= extern ⟨proto⟩
⟨proto⟩ ::= id ‘(‘ ⟨idseq⟩ ‘)
⟨idseq⟩ ::= id ⟨idseq⟩ | ϵ
⟨expr⟩ ::= ⟨expr⟩ ‘ + ‘ ⟨expr⟩ | ⟨expr⟩ ‘ − ‘ ⟨expr⟩ |
⟨expr⟩ ‘ ∗ ‘ ⟨expr⟩ | ⟨expr⟩ ‘/‘ ⟨expr⟩ |
‘(‘ ⟨expr⟩ ‘)‘ | ⟨idexpr⟩ | number
⟨idexpr⟩ ::= id | id ‘(‘ ⟨optexpr⟩ ‘)‘
⟨optexpr⟩ ::= ⟨exprlist⟩ | ϵ
⟨exprlist⟩ ::= ⟨expr⟩ | ⟨expr⟩ ‘, ‘ ⟨exprlist⟩

Mauro Leoncini L&C Anno Accademico 2023/24 28 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Qualche osservazione sulla grammatica

Si nota subito che, in vista del parsing LR, non è stato necessario
introdurre la (non elegante) soluzione di avere identicatori diversi per
funzioni e variabili

Una grammatica per il parsing LR può avere infatti pressi comuni

Riguardo l'uso di produzioni ambigue per le espressioni ricordiamo (si


vedano le slide della lezione introduttiva a Bison) che l'ambiguità
viene risolta con l'uso delle direttive %left e %right
Accorpando le produzioni per le espressioni, abbiamo eliminato alcuni
simboli non terminali intermedi, inutili nell'ottica della costruzione
dell'AST

Mauro Leoncini L&C Anno Accademico 2023/24 29 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

I nodi dell'AST

Dal punto di vista programmativo, l'AST altro non è che una


struttura dati e dunque la prima decisione da prendere riguarda proprio
la struttura da utilizzare

L'idea è di rappresentare ogni nodo come oggetto di una classe

La classe di appartenenza di un nodo può variare (naturalmente in


dipendenza di ciò che il nodo vuole rappresentare), tuttavia tutte le
classi dovranno ereditare da una superclasse comune

Come vedremo, con qualche eccezioni, le classi che andremo a denire


corrisponderanno ai simboli non terminali della grammatica

In generale non esiste però una corrispondenza uno-a-uno fra classi e


non terminali

Inizieremo a riettere su come rappresentare le espressioni

Mauro Leoncini L&C Anno Accademico 2023/24 30 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Rappresentazione delle espressioni

Negli esempi di AST che abbiamo visto all'inizio esistevano


apparentemente nodi diversi anche solo per operatori dierenti
Tale distinzione non deve necessariamente portare all'introduzione di
più classi, che dierirebbero solo per il tipo di operazioni
Per le espressioni introdurremo invece una classe da cui deriveremo 4
classi, corrispondenti a: (1) operatori binari, (2) variabili, (3) costanti
numeriche e (4) chiamata di funzione
Le 4 sottoclassi rappresentano altrettanti elementi costituenti
un'espressione. Esse rappresentano però caratteristiche diverse:
variabili e costanti numeriche corrispondono a foglie dell'ASD e sono
elementi con valore lessicale (di natura dierente)
gli operatori binari denotano nodi interni con due gli; tralasciando il
particolare operatore, richiedono tutti lo stesso trattamento
come variabili e costanti, anche una chiamata di funzione etichetta una
foglia di un AST ma il trattamento degli argomenti (che naturalmente
sono a loro volta espressioni) richiede un collegamento ad un numero
arbitrario di altri ASD
Mauro Leoncini L&C Anno Accademico 2023/24 31 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La gerarchia completa

In tutto introdurremo 9 classi, così organizzate

Root

Seq Prototype Function Expr

Number Variable Binary Call


I nomi eettivi che daremo alle classi sono leggermente dierenti
rispetto alla gura (dove sno stati accorciati per ragioni di spazio)

Tutti i nomi hanno cioè il susso AST che, per le sottoclassi di Expr,
diviene ExprAST
Le classi vengono denite nel le [Link] mentre
l'implementazione dei metodi è data nel le [Link]
Il driver è essenzialmente l'applicazione (in questo caso un front-end
per Kaleidoscope 1.0) che coordina le attività di parser e lexer

Mauro Leoncini L&C Anno Accademico 2023/24 32 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe RootAST
La classe base della gerarchia include solo metodi virtuali (si veda la
prossima slide per un veloce ripasso sull'uso di tali metodi)

typedef std::variant<std::string,double> lexval;


const lexval NONE = 0.0;

class RootAST {
public:
virtual ~RootAST() = default;
virtual RootAST *left() {return nullptr;};
virtual RootAST *right() {return nullptr;};
virtual lexval getLexVal() {return NONE;};
virtual void visit() {};
};

I metodi saranno opportunamente rideniti nelle sottoclassi


Mauro Leoncini L&C Anno Accademico 2023/24 33 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Una digressione: metodi virtuali e loro utilizzo

Si denisce virtuale un metodo dichiarato all'interno di una classe


base e ridenito (overriden) in una classe derivata
Si tratta di uno strumento per implementare polimorsmo a tempo di
esecuzione

Per varie ragioni, può essere necessario fare riferimento ad un metodo


M di una classe derivata D usando un puntatore il cui tipo è quello
di una classe base B
In questo caso, tecnicamente, il compilatore potrebbe sollevare
un'eccezione se B non denisce M oppure se la denisce in modo
diverso

Se M è denita in B come virtuale, a tempo di esecuzione viene


(cercata e) chiamata la funzione corretta denita in D
Per i distruttori questa costruzione è di fatto obbligatoria (per far sì
che venga distrutto l'oggetto giusto)

Mauro Leoncini L&C Anno Accademico 2023/24 34 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe base per le espressioni

La classe ExprASt non include metodi virtuali e potrebbe in teoria non


essere presente

In tal caso tutte le classi erediterebbero direttamente da RootAST


La classe viene introdotta principalmente per una maggiore pulizia
del progetto complessivo

Consideriamo il caso di un'espressione E costituita, ad es., dalla


somma di due (sotto)-espressioni E1 edE2
E1 ed E2 possono essere di uno qualsiasi dei 4 tipi che abbiamo
individuato (numero, identicatore, espressione binaria o chiamata di
funzione)

È chiaro dunque che ci deve essere una classe comune per indicare
queste espressioni

Se la classe fosse direttamente RootAST, potrebbe risultare lecito


comporre un'espressione anche con oggetti delle altre tre classi, ad
esempio SeqAST, ma questo non sarebbe corretto
Mauro Leoncini L&C Anno Accademico 2023/24 35 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe NumberExprAST
Denizione

class NumberExprAST : public ExprAST {


private:
double Val;
public:
NumberExprAST(double Val);
void visit();
lexval getVal() const;
};
Implementazione

NumberExprAST::NumberExprAST(double Val): Val(Val) {};


void NumberExprAST::visit() {
std::cout << Val << " "; };
lexval NumberExprAST::getLexVal() {
lexval lval = Val; return lval; };
Mauro Leoncini L&C Anno Accademico 2023/24 36 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe VariableExprAST
Denizione

class VariableExprAST : public ExprAST {


private:
std::string Name;
public:
VariableExprAST(std::string &Name);
void visit();
lexval getLexVal(); };
Implementazione

VariableExprAST::variableExprAST(std::string &Name):
Name(Name) {};
void VariableExprAST::visit() {
std::cout << Name << " "; };
lexval VariableExprAST::getLexVal() {
lexval lval = Name; return lval; };
Mauro Leoncini L&C Anno Accademico 2023/24 37 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe BinaryExprAST: denizione

class BinaryExprAST : public ExprAST {


private:
char Op;
ExprAST* LHS;
ExprAST* RHS;
public:
BinaryExprAST(char Op, ExprAST* LHS, ExprAST* RHS);
ExprAST* left();
ExprAST* right();
void visit();
};

Mauro Leoncini L&C Anno Accademico 2023/24 38 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe BinaryExprAST: implementazione

BinaryExprAST::BinaryExprAST(char Op, ExprAST* LHS,


ExprAST* RHS): Op(Op), LHS(LHS), RHS(RHS) {};
ExprAST* BinaryExprAST::left() {
return LHS;
};
ExprAST* BinaryExprAST::right() {
return RHS;
};
void BinaryExprAST::visit() {
std::cout << "(" << Op << " ";
LHS->visit();
if (RHS!=nullptr) RHS->visit();
std::cout << ")";
};

Mauro Leoncini L&C Anno Accademico 2023/24 39 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe CallExprAST: denizione

class CallExprAST : public ExprAST {


private:
std::string Callee;
std::vector<ExprAST*> Args;

public:
CallExprAST(std::string Callee,
std::vector<ExprAST*> Args);
lexval getLexVal() const;
void visit();
};

Mauro Leoncini L&C Anno Accademico 2023/24 40 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe CallExprAST: implementazione

CallExprAST::CallExprAST(std::string Callee,
std::vector<ExprAST*> Args): Callee(Callee),
Args(std::move(Args)) {};
lexval CallExprAST::getLexVal() const {
lexval lval = Callee;
return lval;
};
void CallExprAST::visit() {
std::cout<< std::get<std::string>(getLexVal())<< "( ";
for (ExprAST* arg : Args) {
arg->visit();
};
std::cout << ')';
};

Mauro Leoncini L&C Anno Accademico 2023/24 41 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

Le altre classi

Le ultime tre classi sono di natura dierente

Una prima classe, SeqAST, rappresenta la sequenza di istruzioni

Negli AST che andremo a costruire, gli oggetti di tipo SeqAST


costituiscono la dorsale (con linguaggio gurato, diciamo il versante
destro dell'AST)

Le altre due classi rappresentano la denizione di funzioni (classe


FunctionAST) e la denizione di prototipi di funzione (classe
PrototypeAST), quest'ultima utilizzata nella denizione della prima

Mauro Leoncini L&C Anno Accademico 2023/24 42 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe SeqAST: denizione

class SeqAST : public RootAST {


private:
RootAST* first;
RootAST* continuation;

public:
SeqAST(RootAST* first, RootAST* continuation);
RootAST *left();
RootAST *right();
void visit();
};

Mauro Leoncini L&C Anno Accademico 2023/24 43 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe SeqAST: implementazione

SeqAST::SeqAST(RootAST* first, RootAST* continuation):


first(first), continuation(continuation) {};
RootAST* SeqAST::left() { return first; };
RootAST* SeqAST::right() { return continuation; };
void SeqAST:: visit() {
if (first != nullptr) {
first->visit();
} else {
if (continuation == nullptr) {
return;
};
};
std::cout << ";";
continuation->visit();
};
Mauro Leoncini L&C Anno Accademico 2023/24 44 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe PrototypeAST: denizione

class PrototypeAST : public RootAST {


private:
std::string Name;
std::vector<std::string> Args;

public:
PrototypeAST(std::string Name, std::vector<std::string>
lexval getLexVal() const;
const std::vector<std::string> &getArgs() const;
void visit();
int argsize();
};

Mauro Leoncini L&C Anno Accademico 2023/24 45 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe PrototypeAST: implementazione

PrototypeAST::PrototypeAST(std::string Name,
std::vector<std::string> Args):
Name(Name), Args(std::move(Args)) {};
lexval PrototypeAST::getLexVal() const {
lexval lval = Name; return lval; };
const std::vector<std::string>& PrototypeAST::getArgs()
const { return Args; };
void PrototypeAST::visit() {
std::cout << "extern " << Name << "( ";
for (auto it=[Link](); it!=[Link](); ++it) {
std::cout << *it << ' '; };
std::cout << ')';
};
int PrototypeAST::argsize() {
return [Link](); };
Mauro Leoncini L&C Anno Accademico 2023/24 46 / 48
Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe FunctionsAST: denizione

class FunctionAST : public RootAST {


private:
PrototypeAST* Proto;
ExprAST* Body;
bool external;

public:
FunctionAST(PrototypeAST* Proto, ExprAST* Body);
void visit();
int nparams();
};

Mauro Leoncini L&C Anno Accademico 2023/24 47 / 48


Generazione dell'AST Verso l'ASD di Kaleidoscope 1.0

La classe FunctionAST: implementazione

FunctionAST::FunctionAST(PrototypeAST* Proto,
ExprAST* Body): Proto(Proto), Body(Body) {
if (Body == nullptr) external=true;
else external=false; };
void FunctionAST::visit() {
std::cout << std::get<std::string>
(Proto->getLexVal()) << "( ";
for (auto it=Proto->getArgs().begin();
it != Proto->getArgs().end(); ++it) {
std::cout << *it << ' ';
};
std::cout << ')';
Body->visit();
};
int FunctionAST::nparams() {
return Proto->argsize(); };
Mauro Leoncini L&C Anno Accademico 2023/24 48 / 48

Potrebbero piacerti anche