Programmazione orientata agli oggetti in ANSI-C. Lo Screener – Name

Un assegnamento ha la seguente sintassi:

LET è un esempio di keyword. Nel costruire lo screener possiamo ancora decidere quale identificatore rappresenterà LET: scan() estrae un identificatore dalla linea di input e lo passa a screen() che controlla nella tabella dei simboli e ritorna il valore appropriato per token e, almeno per una variabile, un nodo in symbol.

Il riconoscitore scarta LET ma installa la variabile come nodo foglia nell'albero. Per gli altri simboli, come ad esempio il nome di una funzione matematica, potremmo voler applicare new() a qualsiasi simbolo lo screener restituisca per ottenere un nuovo nodo per il nostro albero. Di conseguenza, gli elementi della nostra tabella dei simboli potrebbe, per la maggior parte, avere le stesse funzioni con il dynamic linkage al pari dei nostri nodi dell'albero.

Per una keyword, un Name deve contenere la stringa input e il valore token. In seguito potremmo voler ereditare da Neme: di conseguenza, definiremo la struttura in un file di rappresentazione chiamato Name.r.

struct Name { /* base structure */
const void * type; /* for dynamic linkage */
const char * name; /* may be malloc—ed */
int token;
};

I nostri simboli non “muoiono” mai: non importa se i loro nomi sono costanti o keyword predefinite o stringhe allocate dinamicamente per contenere le variabili usate dall'utente.

Prima che un simbolo possa essere trovato, dobbiamo inserirlo nella tavola dei simboli. Non si può gestire tale operazione chiamando new(Name,...) perchè vogliamo poter supportare simboli più complicati di Name, e allo stesso tempo dobbiamo nascondere l'implementazione della tabella dei simboli. Possiamo però fornire una funzione install() che prende in input un oggetto Name e lo inserisce nella tavola dei simboli. Ecco l'interfaccia dichiarata in Name.h della tabella dei simboli

extern void * symbol; /* —> last Name found by screen() */
void install (const void * symbol);
int screen (const char * name);

Il riconoscitore deve inserire le keywords come LET all'interno della tavola dei simboli prima che essi possano essere trovati dallo screener. Queste keywords possono essere definite in una tabella costante di strutture – non è di particolare importanza per install(). La funzione seguente viene usata per inizializzare il riconoscitore:

#include "Name.h"
#include "Name.r"
static void initNames (void)
{ static const struct Name names [] = {
{ 0, "let", LET },
0 };
const struct Name * np;
for (np = names; np —> name; ++ np)
install(np);
}

Da notare che names[], la tavola delle keywords, non deve necessariamente essere ordinata. Per definire names[] si usa la rappresentazione di Name, ossia includiamo Name.r. Poiché la keyword LET viene scartata, non verranno forniti metodi linkati dinamicamente.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend