Sto cercando di scrivere un semplice compilatore per scopi di apprendimento. Ho letto Dragon Book e Modern Compiler Design e una parte che non capisco è come viene creato e archiviato il Concrete Syntax Tree.
Comprendo che collegando i token prodotti dal Lexer è semplice raccogliere tutti i pezzi di un operatore di assegnazione; ad esempio:
int i = 0;
è piuttosto semplice per raccogliere type
, identifier
e che stiamo assign
su un valore di const_number
zero. E capisco come si presenta questo albero sintattico.
E se è assegnato come un'espressione come:
int i = a * b;
Capisco anche come sarebbe questo albero sintattico concreto.
Ma allora diciamo che ho:
int i = functionCall();
Che aspetto ha questo in un albero di sintassi concreto?
Inoltre, considerando un linguaggio come C che è un insieme di funzioni, con una di esse, la funzione main
viene indicata come punto di ingresso; come si inserisce tutto questo in un albero di sintassi concreto?
Ciascuno ha il suo albero?
La creazione di un'erarchia di tipi Node
per il mio albero, ognuno con le componenti specifiche di cui ha bisogno ha senso per me; ma non come chiama questo fattore nella funzione; a meno che ogni singola funzione sia stata sottolineata.
Informazioni aggiuntive dai commenti
Quindi, diciamo che ho un codice che assomiglia a:
int AddProc(int i, int j)
{
return i + j;
}
void main()
{
int x = 8;
int y = 0;
int z = x + y;
x = AddProc(y,z);
}
Il flusso di token inizia dall'alto verso il basso; semplice; ogni token indica al parser se è un TYPE
o ID
o CONST
o ADD_OP
qualunque. Il primo stadio del parser consiste nel produrre un Concrete Syntax Tree, che viene poi trasformato in un Abstract Syntax Tree.
La mia domanda è: come appare il Concrete Syntax Tree per quanto sopra; e inoltre, anche l'AST?