J'ai lu plusieurs articles, articles et section 4.1.4, chapitre 4 de Compilers: Principles, Techniques, and Tools (2nd Edition) (aka "The Dragon Book") qui traitent tous du sujet de la récupération d'erreur du compilateur syntaxique. Cependant, après avoir expérimenté avec plusieurs compilateurs modernes, j'ai vu qu'ils récupèrent également des erreurs sémantiques , ainsi que des erreurs syntaxiques.
Je comprends assez bien les algorithmes et techniques derrière les compilateurs récupérant des erreurs liées syntaxiquement, mais je ne comprends pas exactement comment un compilateur peut récupérer d'une erreur sémantique.
J'utilise actuellement une légère variation du modèle de visiteur pour générer du code à partir de mon arbre de syntaxe abstraite. Considérez mon compilateur qui compile les expressions suivantes:
1 / (2 * (3 + "4"))
Le compilateur générerait l'arborescence de syntaxe abstraite suivante:
op(/)
|
-------
/ \
int(1) op(*)
|
-------
/ \
int(2) op(+)
|
-------
/ \
int(3) str(4)
La phase de génération de code utiliserait alors le modèle de visiteur pour parcourir récursivement l'arborescence de syntaxe abstraite et effectuer une vérification de type. L'arbre de syntaxe abstraite serait parcouru jusqu'à ce que le compilateur atteigne la partie la plus interne de l'expression; (3 + "4")
. Le compilateur vérifie ensuite chaque côté des expressions et constate qu'elles ne sont pas sémantiquement équivalentes. Le compilateur déclenche une erreur de type. Voici où réside le problème. Que doit faire maintenant le compilateur ?
Pour que le compilateur se remette de cette erreur et continue de vérifier le type des parties externes des expressions, il devrait renvoyer un type ( int
ou str
) d'évaluation de la partie la plus interne de l'expression à la partie la plus interne suivante de l'expression. Mais il n'a tout simplement pas de type à renvoyer . Puisqu'une erreur de type s'est produite, aucun type n'a été déduit.
Une solution possible que j'ai postulée, est que si une erreur de type se produit, une erreur doit être déclenchée et une valeur spéciale qui signifie qu'une erreur de type s'est produite doit être renvoyée aux appels précédents de traversée de l'arbre de syntaxe abstraite. Si les appels de parcours précédents rencontrent cette valeur, ils savent qu'une erreur de type s'est produite plus profondément dans l'arbre de syntaxe abstraite et doivent éviter d'essayer de déduire un type. Bien que cette méthode semble fonctionner, elle semble être très inefficace. Si la partie la plus à l'intérieur d'une expression est au fond de l'arbre de syntaxe abstraite, alors le compilateur devra effectuer de nombreux appels récursifs uniquement pour se rendre compte qu'aucun travail réel ne peut être effectué, et simplement revenir de chacun.
Est-ce que la méthode que j'ai décrite ci-dessus est utilisée (j'en doute). Si oui, n'est-ce pas efficace? Sinon, quelles sont exactement les méthodes utilisées lorsque les compilateurs récupèrent des erreurs sémantiques?