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?