Pour ceux qui ne suivent pas POJ (Pascal sur la JVM) c'est un compilateur qui transforme un sous-ensemble de Pascal en JASM ( Java Assembly) afin que nous puissions utiliser la JVM comme environnement d'exécution.
Dans le dernier post nous avons résolu quelques bugs importants, notamment dans la génération de l'assembly. Dans cet article, nous parlerons de la façon de générer correctement l'assembly pour les phrases imbriquées.
Comme nous compilons pour la JVM, il est nécessaire de détailler le fonctionnement de différents points de cette incroyable machine virtuelle. C'est pourquoi, à différents moments, je détaille le fonctionnement interne de la JVM ainsi que certaines de ses instructions (opcodes).
L'une des fonctionnalités nécessaires pour traiter correctement les phrases imbriquées est la possibilité d'avoir plusieurs contextes dans le analyseur. En effet, si l'analyseur suppose un seul contexte, des phrases de contrôle imbriquées qui génèrent des étiquettes et des sauts (comme if, for, while et répéter) généreraient un adressage de saut incorrect.
Il existe deux manières de gérer les contextes, à savoir :
Habituellement, j'utiliserais l'approche récursive analyseur. Cependant, afin d'implémenter un analyseur récursif avec ANTLR, en raison de la façon dont la grammaire était structurée en POJ, il serait nécessaire d'injecter du code directement dans la grammaire, une approche qui n'est pas recommandée. De ce fait, nous avons opté pour l'approche des contextes d'empilement.
Comme il existait déjà une implémentation de pile qui surveillait les types que l'analyseur empilait/dépilait dans la JVM, afin de ne pas avoir à créer une autre pile pour un type spécifique, nous avons décidé d'en créer une stack générique dans ce PR. En plus de pouvoir profiter de cette implémentation plus tard, je peux toujours refactoriser l'ancien code et supprimer la pile spécifique existante.
Dans ce commit, le analyseur a été modifié pour empiler/dépiler correctement les contextes de fonctions. Fondamentalement, au début de l'analyseur d'une fonction, le contexte est empilé, et à la fin, le contexte est dépilé.
Les phrases de contrôle comme if, for, while et repeat fonctionnaient correctement. Cependant, s'il y avait des phrases imbriquées, POJ ne stockait pas le contexte et finissait par générer par erreur des étiquettes et des sauts. Ici et ici, il a été discuté du fonctionnement de la génération de l'assembly pour ces phrases de contrôle.
Pour l'exemple ci-dessous, qui contient un if imbriqué dans un autre, POJ a généré par erreur les étiquettes et les sauts nécessaires :
program NestedIfs; begin if (1 > 2) then if (2 > 3 ) then writeln('1 > 2 and 2 > 3') else writeln('1 > 2 and 2 <= 3') else writeln('1 <= 2'); end.
Ce bug était connu et j'ai choisi de le résoudre lorsque l'analyseur prenait en charge les contextes.
Dans ce commit, la structure LabelsContext a été créée contenant les labels suivants :
Pour valider la bonne génération de l'assembly, des tests ont été créés pour valider les if imbriqués, les répétitions imbriqués, les while imbriqués ainsi que les for imbriqué. Des tests ont été créés ici pour valider la génération de l'assembly dans le cas de fonctions récursives. De plus, il était nécessaire de mettre à jour le assemblage attendu de tous les tests existants. Enfin, dans ce PR, le analyseur a été mis à jour pour utiliser la nouvelle structure de contexte.
Voici le PR complet de ces changements. Nous avons ici le commit contenant les modifications pour le bon fonctionnement de la phrase if, ici le commit faisant référence à la repeat, ici le commit faisant référence à pendant et ici le commit faisant référence à pour.
Dans le prochain post, nous parlerons de la saisie des données. Il ne faudra plus longtemps avant d'atteindre l'un des objectifs de ce projet : lire un nombre à partir d'une entrée standard et calculer sa factorielle.
Le référentiel avec le code complet et la documentation du projet est ici.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!