L'interprete è stato inizialmente pensato come interprete Scheme. Tuttavia la realizzazione avrebbe dovuto essere modulare in modo da consentire il riutilizzo di alcune sue componenti per realizzare un secondo interprete, questa volta Prolog. In sostanza lo schema progettuale è il seguente:
La gerarchia Sexp (Sexp è l'abbreviazione di Symbolic Expression, o S-expression) è una gerarchia di classi Java ideata per rappresentare la forma interna RI scelta per le frasi del linguaggio Scheme. "Il modello computazionale Lisp - quindi Scheme - si fonda sull'idea di denotare i dati e i programmi attraverso espressioni elementari (atomiche) o composte" (cfr con le dispense del corso). In particolare una espressione atomica può denotare un valore o un simbolo, mentre un'espressione composta può essere formata solo da altre espressioni. Il tutto si riassume tramite la seguente gerarchia:
figura 3.
In essa Sexp è una classe astratta a cui appartengono tutte le espressioni simboliche, ovvero tutte le frasi del linguaggio. AtomSexp e ConsSexp costituiscono rispettivamente le espressioni atomiche e quelle composte. La classe AtomSexp è astratta e da essa derivano due sottoclassi IdentSexp e NilSexp. A NilSexp appartengono le espressioni nulle, indicate con l'atomo predefinito "nil" o con "()". La NilSexp è importante anche perché ad essa appartiene il terminatore delle liste. Le espressioni atomiche non nulle sono delle IdentSexp, nel senso che ciascuna di esse costituisce un identificatore (da cui "ident") che può denotare un simbolo o un valore in funzione del dominio semantico considerato.
In Scheme ogni espressione è un atomo o un'espressione composta. La valutazione di una S-expression avviene secondo il seguente modello:
La gerarchia è quindi utilizzata per costruire
una forma interna adeguata a questo schema. In particolare una ConsSexp
sarà un oggetto costituito da una testa ed una coda. La sua la coda
potrà essere un atomo o una nuova ConsSexp, e così via.
Ora ricordiamo che in Lisp ogni oggetto non atomico
è una lista (Lisp significa List Processing) e la lista è
un oggetto che può essere definito in modo ricorsivo come segue:
La gerarchia così costruita è ideata sul modello computazonale Lisp e quindi ci si potrebbe chiedere a questo punto come può adattarsi ad un modello computazionale diverso, quale potrebbe essere quello di un altro linguaggio. In realtà si deve notare che il modello Lisp è sfruttato per gestire la RI della frase del linguaggio e questa non dipendente dal linguaggio scelto. Dunque il compito del riconoscitore è di costruire una RI in forma di Sexp della frase analizzata.
A riprova di ciò anche l'iterprete Prolog è stato costruito su quella stessa gerarchia.
In figura 2. sono indicate
anche delle utilities. Queste consistono in una serie di classi
Java create per fornire alcune utilità. Fra queste alcune classi
create appositamente per gestire le Sexp: un classe Lexer generica, una
classe per gestire le eccezioni, una classe per costruire un DataBase di
Sexp, una classe che definisce un Visitor astratto per Sexp, etc. In particolare
la classe Lexer è stata realizzata in modo da consentire di costruire
facilmente l'analizzatore lessicale (AL) specifico del linguaggio. L'AL
specifico può essere realizzato definendo una sottoclasse della
classe Lexer in cui si inizializza l'AL e si ridefiniscono i metodi che
devono trattare casi particolare non previsti nella superclasse. L'inizializzazione
consiste nel definire quattro insiemi, uno contenete le primitive (classe
PrimitiveSet), uno contenente i Tokens speciali (classe SpecialSet), una
contenente gli operatori (classe OperatorSet) ed uno contenente i relazionali
(classe RelationalSet).
Delle utilities fanno poi parte anche delle classi
sfruttate per la costruzione dell'interfaccia grafica.