Ho letto diversi articoli, articoli e la sezione 4.1.4, capitolo 4 di Compilatori: Principi, Tecniche e strumenti (2a edizione) (ovvero "Il libro del drago") che trattano tutti l'argomento del recupero degli errori del compilatore sintattico. Tuttavia, dopo aver sperimentato diversi compilatori moderni, ho visto che si sono anche ripresi dagli errori semantici , oltre agli errori sintattici.
Capisco abbastanza bene gli algoritmi e le tecniche dietro i compilatori che recuperano da errori sintatticamente correlati, tuttavia non capisco esattamente come un compilatore possa recuperare da un errore semantico.
Attualmente sto usando una leggera variazione del pattern visitor per generare codice dal mio albero di sintassi astratto. Considera il mio compilatore che compila le seguenti espressioni:
1 / (2 * (3 + "4"))
Il compilatore genererebbe il seguente albero di sintassi astratto:
op(/)
|
-------
/ \
int(1) op(*)
|
-------
/ \
int(2) op(+)
|
-------
/ \
int(3) str(4)
La fase di generazione del codice userebbe quindi il pattern visitor per attraversare in modo ricorsivo l'albero della sintassi astratta ed eseguire il controllo del tipo. L'albero sintattico astratto verrebbe attraversato fino a quando il compilatore non arrivasse alla parte più interna dell'espressione; %codice%. Il compilatore controlla quindi ogni lato delle espressioni e vede che non sono equivalenti semanticamente. Il compilatore genera un errore di tipo. Qui è dove si trova il problema. Cosa dovrebbe fare il compilatore ?
Affinché il compilatore recuperi da questo errore e continui a digitare il controllo delle parti esterne delle espressioni, dovrebbe restituire un tipo ( (3 + "4")
o int
) dalla valutazione della parte più interna dell'espressione, nella prossima parte più interna dell'espressione. Ma semplicemente non ha un tipo da restituire . Poiché si è verificato un errore di tipo, non è stato dedotto alcun tipo.
Una possibile soluzione che ho postulato è che se si verifica un errore di tipo, deve essere generato un errore e un valore speciale che indica che si è verificato un errore di tipo deve essere restituito alle precedenti chiamate di attraversamento dell'albero della sintassi astratta. Se le chiamate di attraversamento precedenti incontrano questo valore, sanno che un errore di tipo si è verificato più in profondità nell'albero di sintassi astratto e dovrebbe evitare di tentare di dedurre un tipo. Anche se questo metodo sembra funzionare, sembra essere molto inefficiente. Se la parte più interna di un'espressione è immersa nell'albero di sintassi astratto, il compilatore dovrà effettuare molte chiamate ricorsive solo per rendersi conto che non è possibile eseguire alcun lavoro reale e semplicemente tornare da ciascuna di esse.
È usato il metodo che ho descritto sopra (ne dubito). Se è così, non è efficiente? In caso contrario, quali sono esattamente i metodi utilizzati quando i compilatori recuperano da errori semantici?