Pour ceux qui ne suivent pas POJ (Pascal sur la JVM) est un compilateur qui transforme unsubsetde 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 duassembly. Dans cet article, nous expliquerons comment générer correctement l'assemblypour 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, à plusieurs reprises, 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 leparser. En effet, si leparserne suppose qu'un seul contexte, les phrases de contrôle imbriquées qui génèrent deslabelset des sauts (telles queif,for,whileetrepeat) généreraient un adressage de saut incorrect. .
Il existe deux manières de gérer les contextes, à savoir :
parser. Cependant, pour implémenter unanalyseurrécursif avec ANTLR, en raison de la manière dont la grammaire a été structurée en POJ, il serait nécessaire d'injecter du code directement dans la grammaire, une approche qui n'est pas recommandée. En conséquence, nous avons opté pour l’approche d’empilement de contextes.
Comme il existait déjà une implémentation de pile qui surveillait les types que leparserempilait/dépilait dans la JVM, afin de ne pas avoir à créer une autre pile pour un type spécifique, nous avons décidé de créer unestackgé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 lastackspécifique existante.
Dans cecommit, leparsera été modifié pour empiler/dépiler correctement les contextes de fonctions. Fondamentalement, au début duparserd'une fonction, le contexte est empilé, et à la fin, le contexte est dépilé.
Phrases imbriquées Les phrases de contrôle telles queif,pour,pendantetrépéteront fonctionné correctement. Cependant, s'il y avait des phrases imbriquées, POJ ne stockait pas le contexte et finissait par générer par erreur lesétiquetteset les sauts. Ici et ici, il a été discuté du fonctionnement de la génération deassemblypour ces phrases de contrôle.
Pour l'exemple ci-dessous, qui contient unifimbriqué dans un autre, POJ a généré par erreur lesétiquetteset 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.
labelssuivants :
assembly, des tests ont été créés pour valider lesif'simbriqués, lesrepeat'simbriqués, les while imbriqués ainsi que lespourimbriqués. Des tests ont été créés ici pour valider la génération duassemblydans le cas de fonctions récursives. De plus, il a fallu mettre à jour leassemblyattendu de tous les tests existants. Enfin, dans ce PR, leparsera été mis à jour pour utiliser la nouvelle structure de contexte.
Voici le PR complet de ces changements. Ici nous avons lecommitcontenant les changements pour le bon fonctionnement de la phraseif, ici lecommitfaisant référence àrepeat, ici lecommitfaisant référence àwhileet ici lecommitfaisant référence àpour.
Prochaines étapes Dans le prochain article, 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. Code de projet complet 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!