Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Compylateur
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

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 !


Précédente 1, 2, 3 ··· 10 ··· 12, 13, 14, 15, 16, 17, 18, 19, 20 Suivante
Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 18/06/2020 11:38 | #


Pour moi le 1/b c'est du hack

Eh ben désolé de te décevoir mais c'est la représentation correcte et non-redondante.

La parenthèse ouvrante n'est pas oubliée.

Et f((a+b)*2) ça donne quoi ?
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 18/06/2020 11:49 | #


C'pas bien d'essayer de me piéger
>>> compylateur("f((a+b)*2)")
--- Tokens ---
('VAR', 'f')
('LPAR', '(')
('LPAR', '(')
('VAR', 'a')
('PLUS', '+')
('VAR', 'b')
('RPAR', ')')
('MULTI', '*')
('NUM', 2)
('RPAR', ')')


--- AST ---
Function : f
  Parameter : #1
    Operation : *
      Operation : +
        Variable : a
        Variable : b
      Number : 2

"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 18/06/2020 12:01 | #


Avec le code que t'as posté tout à l'heure ? o_o
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 18/06/2020 12:02 | #


J'ai inversé le if et le else entre temps

Edit :
J'ai ce code actuellement
def fct(self):
        param = list()
        while self.token_ahead.type != "RPAR":
            if self.token_ahead in ("COMMA", "RPAR"): self.expect(["COMMA", "RPAR"])
            else:
                param.append(Node("Parameter", "#{}".format(len(param)+1), self.expr()))
        return param

"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 18/06/2020 12:53 | #


Ok, avec le code de tout à l'heure ça serait pas passé.

Tu as remarqué que tu acceptes f(x,,y) et que tu ne lis pas la parenthèse fermante ?
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 18/06/2020 13:15 | #


J'ai pas compris pourquoi je ne lit pas la parenthèse fermante… ?

Et oui j'accepte f(x,,y) mais je ne suis pas sûr… Est-ce que je suis obligé de faire remonter une erreur de syntaxe ou est-ce que l'on peut considérer que c'est une faute de frappe ? C'est pas très propre ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Mactul Hors ligne Membre Points: 699 Défis: 0 Message

Citer : Posté le 18/06/2020 13:36 | #


personnellement, je préfère toujours qu'un compilo me retourne une erreur plutot qu'il essaye de comprendre ce que j'ai voulu faire

si tu prend exemple sur js, le fait qu'il autorise "5"+ 3 par exemple pose plein de pb...
notament

"5" - 3 = 2 mais "5" + 3 = "53"
Mes programmes
Cliquer pour enrouler

Venez me rejoindre sur mon nouveau serveur Discord dédié a la programmation sur toutes les plateformes
https://discord.gg/bzfymHQ

Venez vous instruire, dans ce magnifique cours sur les Intelligences Artificielles que j'ai créé:
http://reseaux-neurones-a--z.ml/
Faites apprendre des choses à une machine, faites reconnaître à un ordi des images...
Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 18/06/2020 13:39 | #


Shadow15510 a écrit :
J'ai pas compris pourquoi je ne lit pas la parenthèse fermante… ?

Car tu n'appelles pas self.expect() pour récupérer le token de parenthèse fermante. Tu comprends bien que ton if n'attrape que les virgules car si le prochain token est une parenthèse fermante, tu auras quitté la boucle avant même d'atteindre le if !

Et oui j'accepte f(x,,y) mais je ne suis pas sûr… Est-ce que je suis obligé de faire remonter une erreur de syntaxe ou est-ce que l'on peut considérer que c'est une faute de frappe ? C'est pas très propre ?

Ça devrait être une erreur de syntaxe. Ta boucle devrait, en principe, garantir que les virgules et les expressions sont alternées. On peut par exemple procéder comme ceci :

def fct(self):
  param = list()
  while self.token_ahead.type != "RPAR":
    param.append(self.expr())
    if self.token_ahead.type == "RPAR":
      break
    self.expect(["COMMA"])
  self.expect(["RPAR"])
  return param

Ici chaque tour de boucle lit une expression et une virgule. On autorise uniquement une virgule avant la tout dernière parenthèse fermante, ce qui est classique et permet d'écrire des appels sur plusieurs lignes dans les langages impératifs, comme ça :

super_longue_fonction(
   paramètre_1,
   gros_appel(x, y, z, t) * produit_tensoriel(espace_bizarre),
   inversion_paranormale_métrique(U),
)

Tu vois l'idée je pense.

Mactul a écrit :
"5" - 3 = 2 mais "5" + 3 = "53"

Ça ça relève plutôt du typage et de l'analyse sémantique... mais c'est un bon exemple ! Effectivement, un compilateur doit le plus strict possible pour éviter les malentendus. Si le langage n'est pas rigoureux les programmes écrits avec ne le seront pas non plus !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 18/06/2020 18:13 | #


Okay… Je retouche ça ! Merci

Ajouté le 19/06/2020 à 09:44 :
Du coup j'ai ce code pour les appels de fonctions :
def fct(self):
      param = list()
      while self.token_ahead.type != "RPAR":
        param.append(Node("Parameter", "#{}".format(len(param)+1), self.expr()))
        if self.token_ahead.type == "RPAR":
          break
        self.expect(["COMMA"])
      self.expect(["RPAR"])
      return param

Ce qui me donne des AST (ou CST… ?) comme ça :
>>> compylateur("f((a+2), 12)")
--- Tokens ---
('VAR', 'f')
('LPAR', '(')
('LPAR', '(')
('VAR', 'a')
('PLUS', '+')
('NUM', 2)
('RPAR', ')')
('COMMA', ',')
('NUM', 12)
('RPAR', ')')


--- AST ---
Function : f
  Parameter : #1
    Operation : +
      Variable : a
      Number : 2
  Parameter : #2
    Number : 12


Du coup là on en a terminé avec les expressions mathématiques ? Tu avais parlé du plus unaire, mais que c'était optionnel… C'est important ? Et quels avantages / inconvénient pour la suite ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 10:30 | #


C'est pas mal ! J'en ai pas parlé tout à l'heure, mais ton noeud "Parameter" ne... joue aucun rôle. De la même façon que les arguments de + sont juste mis ensemble dans une liste, les arguments de la fonction peuvent être mis ensemble dans une liste. Il n'y a pas besoin d'avoir un noeud spécifique. D'ailleurs ça se voit : ton noeud "Parameter" ne "calcule" rien, contrairement à tous les autres.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 10:31 | #


C'est juste je l'enlève
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 10:56 | #


Le plus unaire on s'en fout, c'est pour la décoration et l'exhaustivité. Je pense qu'il y a d'autres priorités maintenant !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 10:59 | #


Les conditions et comparaisons ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 11:16 | #


Par exemple ouais. Mais n'oublie pas d'écrire la grammaire au propre avant de coder ! Je sais que ça peut être chiant, mais c'est là que tu vois vraiment ce que tu fais !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 11:24 | #


Ouaip

Je pensais à un truc comme ça :
comparaison -> atome COMP atome
condition -> comparaison | (comparaison LOGI comparaison)*


Je me dit qu'il faut que je sépare les tokens COMP en type de comparaison, du coup j'aurais une flotte de méthode pour les comparaisons comme pour somme -> produit -> puissance et la règle comparaison serait l'équivalent de la méthode expr pour les opérations ^^. Du coup ça ferais une grammaire plus comme ça :

comp_sup -> comp_sup_ega > comp_sup_ega
comp_sup_ega -> comp_inf >= comp_inf
comp_inf -> comp inf_ega < comp_inf_ega
comp_inf_ega -> comp_ega <= comp_ega
comp_ega -> comp_dif == comp_dif
comp_dif -> atome != atome

comparaison -> comp_sup
condition -> comparaison | (comparaison LOGI comparaison)*


Déjà voir si je suis pas partit n'importe où et ensuite voir pour détailler les opérations logiques avant de coder des comparaisons
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 11:33 | #


comparaison -> atome COMP atome

Tu as recommencé ! Tu as été coller des atomes là où tu attends des expressions arithmétiques ! On a pourtant défini expr spécifiquement pour éviter ce problème !

Je me dit qu'il faut que je sépare les tokens COMP en type de comparaison

Oui, mais tu peux utiliser la même méthode pour >, ≥, < et ≤ qui ont la même priorité (traditionnellement), par contre il t'en faudra une autre pour = et ≠ qui sont moins prioritaires (traditionnellement). Tu peux voir ces deux groupes comme addition/soustraction et multiplication/division.

Et n'oublie pas que tes opérateurs logiques ont aussi une priorité, c'est le NOT, puis le AND, puis le OR, donc il te faut trois règles pour gérer ces choses-là
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 11:40 | #


Oui, j'avais oublié que expr est le plus général xD du coup ma grammaire pour les comparaisons c'est juste :
general_comp -> comp_dif (SUP | SUP_EGA | INF | INF_EGA) comp_dif
comp_dif -> comp_ega DIF comp_ega
comp_ega -> expr EGA expr

?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 12:09 | #


Plusieurs choses... d'abord là tu ne tiens pas compte de l'associativité (mais c'est pas un problème). Ensuite la priorité de comp_dif et comp_ega devrait être dans l'autre sens (on s'autorise à comparer des booléens pour l'égalité donc on veut pouvoir écrire Si x≤2 == y>3). Enfin on peut aussi comparer des expressions pour l'égalité donc tu devrais avoir un moyen de créer un comp_ega avec juste une expression.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 12:13 | #


Là j'ai plus de mal à suivre… si j'ai bien compris, ma grammaire devient ça ?
comp_ega -> expr | comp_dif EGA comp_dif
comp_dif -> general_comp DIF general_comp
general_comp -> expr (SUP | SUP_EGA | INF | INF_EGA) expr

"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24673 Défis: 170 Message

Citer : Posté le 19/06/2020 12:19 | #


Plutôt quelque chose comme ça.

general_comp -> expr (SUP | SUP_EGA | INF | INF_EGA) expr
comp_ega -> general_comp | expr (EGA | DIF) expr | general_comp (EGA | DIF) general_comp
# Les opérateurs logiques utilisent ensuite comp_ega comme un atome

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 19/06/2020 13:00 | #


Ah ok !
Donc pour les opérateurs logiques j'ai :
or -> and OR and
and -> not AND not
not -> comp_ega | NOT comp_ega

c'est ça ?

Pour la méthode general_comp j'ai ce code :
def general_comp(self):
        elmnt_1 = self.expr()
        comp = self.expect("SUP", "SUP_EGA", "INF", "INF_EGA")
        elmnt_2 = self.expr()
        return Node("Comparison", comp.type, elmnt_1, elmnt_2)


Edit : Finalement je me demande si c'est pas plus pratique d'avoir comme règle :
general_comp -> expr | expr (SUP | SUP_EGA | INF | INF_EGA) expr ? Comme ça, je peux simplifier la règle comp_ega en
comp_ega -> general_comp | general_comp (EGA | DIF) general_comp ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Précédente 1, 2, 3 ··· 10 ··· 12, 13, 14, 15, 16, 17, 18, 19, 20 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 131 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd