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 28/06/2020 18:54 | #
Ah ok, donc l'AST :
Statement : while
Comparison : INF
Variable : a
Number : 5
Block :
Assignement :
Variable : a
Operation : +
Variable : a
Number : 1
Display : a
le nœud Block :… ? Fin je pensais qu'on pouvais en enlever un
Je pense à l'affichage du texte, Afficher "A = ", a
Okay ! Ça avance !
Citer : Posté le 28/06/2020 22:37 | #
C'est difficile d'enlever le noeud bloc. Pour l'instant il est très bien là ; il a une sémantique (exécuter séquentiellement), donc il y a toutes les raisons de le garder.
Dans ton cas qui est similaire à Python 2, Afficher est une "commande", en fait c'est un statement à part entière au lieu d'être une fonction comme printf(). Donc oui tu peux ajouter une règle pour ça.
Citer : Posté le 29/06/2020 08:10 | #
Ok, merci !
Du coup j'avais en tête la grammaire : display -> DISPLAY (TEXT | VAR | NUM) ((COMMA (TEXT | VAR | NUM |))*) ?
Citer : Posté le 29/06/2020 09:49 | #
Tu as encore fait l'erreur de mettre des choses trop restrictives ! Même Basic Casio te laisse écrire A+2◢ !
Citer : Posté le 29/06/2020 09:54 | #
AH
Du coup il faut aussi gérer les expressions mathématiques… Donc la grammaire deviendrait : display -> DISPLAY (expr | TEXT) (COMMA (expr | TEXT))*? ?
J'ai un autre problème aussi : je ne gère plus les demandes utilisateurs pour une raison encore inconnue…
Citer : Posté le 29/06/2020 10:01 | #
Eh bien oui ça doit donner un truc comme ça. Tu devrais toujours utiliser expr quand c'est pas ambigu !
Citer : Posté le 29/06/2020 10:03 | #
Okay, merci
Du coup je cherche pourquoi je ne peux plus entrer de variable et j'implémente la nouvelle grammaire de display
Ajouté le 29/06/2020 à 10:40 :
Bon… du coup tout marche !
--- Tokens ---
('REQUEST', 'saisir')
('VAR', 'a')
('IF', 'si')
('VAR', 'a')
('EGA', 'est égal à')
('NUM', 2)
('THEN', 'alors')
('DISPLAY', 'afficher')
('TEXT', '"gagné !"')
('ELSE', 'sinon')
('DISPLAY', 'afficher')
('TEXT', '"perdu…"')
('END_IF', 'fin si')
--- AST ---
Block :
User's request :
Variable : a
Statement : if
Comparison : EGA
Variable : a
Number : 2
Block :
Display :
Text : "gagné !"
Statement : else
Block :
Display :
Text : "perdu…"
Citer : Posté le 29/06/2020 10:41 | #
Comment ça se fait que le else est dans le if ?
Citer : Posté le 29/06/2020 10:42 | #
Euh… ben… J'ai foutu la règle du Else, dans le celle du if x))
Ajouté le 29/06/2020 à 10:47 :
Mais du coup je ne vois pas comment faire autrement ?
Citer : Posté le 29/06/2020 11:10 | #
Y'a pas besoin d'un noeud ici parce que le else n'a pas de sémantique (tout est dans le if). Il te suffirait d'avoir une liste de conditions/code dans le if, un truc de la forme [ (condition1, block1), (condition2, block2), ..., (condition_n, block_n), (block_else) ].
Citer : Posté le 29/06/2020 11:16 | #
Ah ok ! J'essaye
Ajouté le 29/06/2020 à 11:35 :
Du coup je vais avoir un nœud statement_if et après des nœuds : block et conditions… ?
Citer : Posté le 29/06/2020 11:36 | #
Tu dois avoir un noeud statement_if qui fonctionne un peu comme le noeud somme où tous les arguments sont dans une liste.
Citer : Posté le 29/06/2020 11:39 | #
Ahh okayy ! Merci !!
Ajouté le 29/06/2020 à 12:58 :
Du coup j'ai ça maintenant :
--- Tokens ---
('REQUEST', 'saisir')
('VAR', 'a')
('IF', 'si')
('VAR', 'a')
('EGA', 'est égal à')
('NUM', 2)
('THEN', 'alors')
('DISPLAY', 'afficher')
('TEXT', '"gagné !"')
('ELSE', 'sinon')
('DISPLAY', 'afficher')
('TEXT', '"perdu…"')
('END_IF', 'fin si')
--- AST ---
Block :
User's request :
Variable : a
Statement : if
Comparison : EGA
Variable : a
Number : 2
Block :
Display :
Text : "gagné !"
Block :
Display :
Text : "perdu…"
Citer : Posté le 29/06/2020 12:59 | #
Presque. Un else if ça donne quoi ?
Citer : Posté le 29/06/2020 13:04 | #
Le lexer confond sinon, si avec ELSE COMMA IF x) du coup c'est complétement inopérant… xD Il faut faire une grammaire pour la détection de elif ?
Ajouté le 29/06/2020 à 13:42 :
Bon, j'ai joué sur l'ordre d'appel des tokens… x) C'est pas super, mais ça tient… J'ai ça :
--- Tokens ---
('REQUEST', 'saisir')
('VAR', 'a')
('IF', 'si')
('VAR', 'a')
('EGA', 'est égal à')
('NUM', 2)
('THEN', 'alors')
('DISPLAY', 'afficher')
('TEXT', '"gagné !"')
('ELIF', 'sinon , si')
('VAR', 'a')
('INF_EGA', 'est inférieur ou égal à')
('NUM', 5)
('COMMA', ',')
('DISPLAY', 'afficher')
('TEXT', '"perdu…"')
('ELSE', 'sinon')
('DISPLAY', 'afficher')
('TEXT', '"trop grand !"')
('END_IF', 'fin si')
--- AST ---
Block :
User's request :
Variable : a
Statement : if
Comparison : EGA
Variable : a
Number : 2
Block :
Display :
Text : "gagné !"
Comparison : INF_EGA
Variable : a
Number : 5
Block :
Display :
Text : "perdu…"
Block :
Display :
Text : "trop grand !"
Citer : Posté le 29/06/2020 14:28 | #
Ah, je vois, mais c'est normal ça. Dans un lexer, si à la position courante on peut lire plusieurs tokens différents, il faut toujours prendre le plus long.
Donc sinon ça a l'air pas mal, nice nice.
Citer : Posté le 29/06/2020 14:36 | #
Là j'ai juste mis sinon, si avant sinon dans la liste m'enfin ça marche
Du coup il reste quoi à faire du côté de l'analyse syntaxique ? Pour l'instant on ne gère pas les fonctions… ni les fonctions mathématiques (sin cos, log…) ni les fonctions en programmation… ? Fin, j'ai l'impression que les bases sont là, mais qu'il manque encore plein de choses essentielles pour que ce soit véritablement fonctionnel et l'analyse sémantique ne vas gérer tout ça… ?
Citer : Posté le 29/06/2020 14:39 | #
Parfaitement. Il reste encore plein de trucs à faire. Mais je pense qu'il est temps que tu puisses écrire des programmes simples et les exécuter pour pouvoir passer aux premiers tests unitaires. C'est jamais une bonne idée de rester si longtemps sans tests unitaires.
Citer : Posté le 29/06/2020 14:41 | #
D'accord
Du coup on reviendra sur les autres fonctionnalités plus tard ?
C'est quoi les tests unitaires ?
Citer : Posté le 29/06/2020 14:48 | #
Un test unitaire c'est un tests qui évalue une fonctionnalité précise de ton projet. Écrire des tests unitaires consiste dans ton cas à écrire des programmes qui utilisent chacun des fonctionnalités spécifiques de ton langage. Chaque tests contient aussi (d'une façon ou d'une autre) la solution du test, ici ce que le programme doit afficher. Ensuite chaque fois que tu fais des modifications tu lance un testeur qui va exécuter tous les tests et vérifier que toutes les réponses sont justes.
Par exemple sur l'interpréteur fx-92 SC+ j'ai une liste de tests unitaires ici et un script qui les lance ici. Pour la fx-92 SC+, l'enjeu est surtout de tracer exactement la bonne image au pixel près donc les tests unitaires contiennent aussi un mécanisme pour comparer l'image produite avec une image de référence. Dans ton cas tu compareras sans doute uniquement la sortie du script.
Citer : Posté le 29/06/2020 15:08 | #
Ah ok… x) c'est puissant et monstrueux comme travail… xD