Sfondo
Attualmente sto progettando il mio linguaggio di programmazione come progetto di ricerca.
Ho fatto la maggior parte della grammatica e scritto come grammatica context-free, e dovrebbe funzionare così com'è. - Ora sto lavorando al compilatore attuale che dovrebbe tradurre la lingua in x86 binary assembly code
, in particolare, sto lavorando su parser
(il front-end).
La sintassi del linguaggio è, per la maggior parte, molto simile a Java / C / C ++. Il parser, che costruisce una rappresentazione intermedia fuori dal codice sorgente, funziona come segue:
La grammatica è costruita come un grande albero in cui il vero codice sorgente determina solo le foglie; Ogni variabile sintattica (o non terminale) ha una propria classe e ognuna di queste classi ha un metodo static get(byte[] source, int offset)
che restituisce una nuova foglia (nodo) o null
se la sintassi del codice sorgente non si adatta a questa struttura non terminale.
Sto utilizzando una variazione di predictive parsing
, a proposito.
Per il non terminale DataType
, ho scelto la seguente struttura grammaticale:
DataType:
PrimitiveDataType
| ArrayDataType
| ComplexDataType
ArrayDataType:
DataType []
Ho detto che questo linguaggio è orientato agli oggetti?
Quindi il problema qui è che quando viene chiamato il metodo DataType
di get
, prima controlla se il seguente è un tipo di dati primitivo, viene chiamato il metodo PrimitiveDataType
get
. Supponendo di disporre di un array, restituire null
, quindi continua a verificare se è un ArrayDataType
, chiamando il metodo get
.
Problema
Gli array possono essere creati con qualsiasi tipo di dati, inclusi gli array stessi (che apparirebbero come Type[][]
). Quindi, cosa farebbe il metodo ArrayDataType
di get
è di nuovo chiamare il metodo DataType
get
per capire di che tipo è la matrice.
Sfortunatamente, è qui che la mia implementazione del parser fallirebbe perché questo comportamento si traduce in un loop!
Domanda
Ci sarebbero alternative di progettazione buone / migliori a questo?