Compylateur
Posté le 08/05/2020 14:00
Bonjour à tous !
Il y a quelques temps j'ai fait un 'compilateur' qui permet d'exécuter un algorithme en langage naturel en le 'traduisant' en Python. Le code est atroce et repose sur un remplacement entre les commandes en langage naturel et les commandes en Python (à coup de dictionnaires et de tests conditionnels
)… J'aimerais faire de ce projet un 'vrai' compilateur
(on reste sur du Python
). Et j'ai quelques questions :
- La phase d'analyse lexicale repose pour l'instant sur une recherche et un replacement, avec un dictionnaire qui contient en clés les commandes en langage naturel, et en items, les commandes correspondantes en Python… Je me doute que ce n'est pas pertinent…
En fait l'analyse lexicale est mélangée à la phase d'analyse syntaxique.
- Comment faire pour basculer du langage naturel au Python ? Faut-il forcément passer par un hard code, ou est-ce que d'autre technique plus esthétiques existent ?
- L'analyse syntaxique est un bête
replace basé sur un dico… Du coup ça revient à la question précédente : comment éviter le hard code ?
- La phase sémantique… Je ne suis pas sûr d'avoir bien compris toutes les subtilités…
Dans mon cas, après le remplacement bête et méchant, la syntaxe Python n'est pas bonne, du coup je passe à travers différents tests conditionnels pour avoir un 'vrai' script fonctionnel… Encore une fois le hard code à coup de
if me plaît moyen…
- En derniers je refait un passage sur mon code généré et j'ajoute les alinéas. Est-ce que je devrais les gérer plus tôt (je pense à la phase d'analyse syntaxique… mais le placement des alinéas dépend du contexte du code, et sur une ligne donnée je vois pas trop comment faire…
Merci d'avance !
Citer : Posté le 29/06/2020 15:08 | #
Ah ok… x) c'est puissant et monstrueux comme travail… xD
Citer : Posté le 29/06/2020 15:09 | #
C'est indispensable surtout !
Citer : Posté le 29/06/2020 15:10 | #
Ok… je pense commencer demain ?
Ajouté le 01/07/2020 à 16:32 :
Du coup mes tests unitaires vont se présenter sous la forme d'une multitude de fichiers *.txt ? Et ensuite une fonction par tests unitaire… ?
Citer : Posté le 02/07/2020 08:55 | #
Par exemple oui. Tu veux avoir pour chaque test un fichier truc.txt avec la solution dans truc.solution. Avec un script tu vas exécuter tous les .txt et à chaque fois vérifier que le programme affiche exactement ce qui est dans le .solution.
Tu n'as pas besoin d'avoir "une fonction par test unitaire", il te suffit de faire une recherche des fichiers .txt et de tous les lancer.
Citer : Posté le 02/07/2020 09:28 | #
Okay… j'essaye d'en faire pour voir si c'est j'ai compris et je reviens
Merci !
Ajouté le 11/07/2020 à 14:37 :
Je commence à regarder les tests unitaires de plus près… Par exemple je peux avoir
afficher "2" dans un *.txt et dans le *.solution j'ai 2 ? Mais comment je l'exécute ? Le compilateur n'est pas du tout au point ?
Citer : Posté le 11/07/2020 15:45 | #
Exactement !
Ben il faut que tu ajoutes des fonctions pour interpréter ton AST (ie. exécuter le programme). Ensuite tu fais plus ou moins comme mon script pour la fx92, tu recherches les fichiers .txt dans le dossier de tests, pour chacun d'eux tu lances l'interpréteur dessus en capturant la sortie standard, et tu compares aux contenus du fichier .solution associé.
Citer : Posté le 11/07/2020 15:57 | #
Ah justement… on fait ça comment ? Il faut générer du code ? Mais et l'analyse sémantique… ?
Citer : Posté le 11/07/2020 16:06 | #
Ah ! Mais tu n'es pas obligé d'avoir le compilateur complet pour tester. Ici on veut juste vérifier que le parser marche bien, donc les priorités opératoires, l'affichage, et c'est à peu près tout. Pour ça un interpréteur d'AST suffit. Quand tu auras le compilateur complet il ne sera pas trop tard pour l'enlever si tu n'en veux pas. Mais c'est mieux de l'avoir maintenant pour élimine les bugs au fur et à mesure.
Citer : Posté le 11/07/2020 16:16 | #
Okay ! Donc plutôt que d'avoir 2 dans *.solution avoir l'AST complet serait mieux ?
Citer : Posté le 11/07/2020 16:20 | #
Ah ben si tu pouvais faire ça ce serait encore plus direct. Mais ça va vite être casse-pieds de modifier toutes tes solutions chaque fois que tu changes la fonction d'affichage des AST.
Citer : Posté le 11/07/2020 16:36 | #
Okay… Donc la vraie solution c'est de coder un interpréteur d'AST… et d'effectuer mes tests…
Citer : Posté le 11/07/2020 16:43 | #
Ça a pas besoin d'être très élaboré, juste bien tester toute la grammaire pour que tu puisses passer à la suite sans qu'il y ait de bugs dans le parser.
Citer : Posté le 11/07/2020 16:47 | #
Justement… j'arrive à comprendre comment… ? Pour l'instant j'ai un AST, mais c'est très… abstrait… Il faut faire une fonction qui prend en argument l'AST… ?
Citer : Posté le 12/07/2020 07:57 | #
Oui, une fonction qui prend en argument l'AST et l'interprète. Ce n'est pas très difficile ; par exemple, si tu croises un noeud +, tu appelles récursivement la fonction d'interprétation pour calculer la valeur des opérandes, et ensuite tu fais sum() sur les résultats.
Citer : Posté le 12/07/2020 09:02 | #
Ah ok ! J'essaye ça
Citer : Posté le 21/05/2023 19:59 | #
Coucou par ici ! o/
Oui je sais, j'étais en terminale, j'étais jeune beau et intelligent, maintenant je fais de la physique… Mais ça m'intéresse toujours de continuer à comprendre comment les compilo fonctionnent.
Dans ce qu'il reste à faire pour que ce compilateur soit à peu près opérationnel, c'est de tester le parser à fond et d'attaquer l'analyse sémantique, dernière étape de la création de ce petit test grandeur nature pour comprendre le fonctionnement d'un compilateur.
Pour les tests unitaires, en fait, il faut juste que je les écrives, la fonction d'interprétation de l'AST est presque terminée sinon complètement terminée… Faut aussi que je me remette un peu dans le code, mais il n'est pas trop sale donc ça passe… xD
Pour l'analyse sémantique, là je nage complètement… Globalement je sais que ça permet de typer les expressions pour éviter les conneries du genre 2 + "1" = "3" (Ooops pardon Java ) mais je n'ai aucune idée de comment le programmer ni rien… ^^'
Citer : Posté le 21/05/2023 20:05 | #
L'analyse sémantique c'est un peu quelque chose d'à-la-carte. C'est le moment où tu vérifies que le programme qui t'as été donné est valide par rapport aux règles du langage. Par exemple, en C, c'est là qu'on détermine si quand tu écris x c'est un variable locale de la fonction ou une globale (et si elle existe, déjà), c'est là qu'on vérifie que les types sont corrects, et c'est aussi là qu'on décide de détails du genre comment les éléments des structures vont être agencés en mémoire.
Tu noteras qu'en Python on ne vérifie pas du tout le type et l'existence des variables à la compilation : ça se fait à l'exécution. Donc ça dépend vraiment des fonctionnalités de ton langage. Le but de l'analyse sémantique c'est bien de vérifier que le code est valide et ensuite de calculer toutes les informations dont tu as besoin pour pouvoir passer à la génération de code.
La génération de code d'ailleurs, étant l'étape suivante, le moment où tu produis un autre programme (généralement de même sémantique que le premier) dans le langage de sortie
Citer : Posté le 21/05/2023 21:12 | #
Ok, je comprends un peu mieux, je pense que plus je vais avancer, mieux je comprendrai avec l'implémentation…
Dans l'idée, j'aimerais avoir un fichier *.py en sortie donc si en Python on ne vérifie pas grand chose… L'analyse sémantique va être rapide, non ?
Citer : Posté le 21/05/2023 21:17 | #
Si le fait que ton programme marche n'est pas une priorité, oui
Python délaie juste les check au moment de l'exécution
Mais ils sont fait quand même
Citer : Posté le 21/05/2023 21:20 | #
Oui, mais du coup, ce n'est pas vraiment mon problème ? Ou alors il faut que je vérifie tout ?
Tout vérifier permettrait de savoir dès la compilation si un truc ne va pas, c'est vrai que c'est quand même mieux…
Bon, à la limite pour l'instant, j'en suis toujours à "Comment mon programme marche ? Est-ce qu'il marche ?" et "Écrire des tests" xD
Citer : Posté le 21/05/2023 21:49 | #
Dans l'idée, j'aimerais avoir un fichier *.py en sortie donc si en Python on ne vérifie pas grand chose… L'analyse sémantique va être rapide, non ?
Tu prends la question dans le mauvais sens : la réponse à "que doit faire l'analyse sémantique ?" elle dépend de ce que ton langage il a comme fonctionnalités.
Si ton langage a des variables statiques (ie. fixées à la compilation) comme le C, alors tu dois vérifier que toutes les variables utilisées sont déclarées. Peu importe que tu génères du Python ou de l'assembleur à la fin. Le rôle premier du compilateur avant de générer du code c'est de déterminer si le programme est valide et donc c'est ça que tu dois avoir en tête.
Je n'ai plus trop en tête à quoi ton langage ressemble... si tu as un exemple sous la main et/ou si tu te souviens de ses fonctionnalités ce serait utile.