Posté le 08/05/2020 14:00
)… J'aimerais faire de ce projet un 'vrai' compilateur
(on reste sur du Python
). Et j'ai quelques questions :
En fait l'analyse lexicale est mélangée à la phase d'analyse syntaxique.
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…
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2025 | Il y a 73 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
Citer : Posté le 09/06/2020 14:21 | #
Ah mais ça c'est faux !
Citer : Posté le 09/06/2020 14:25 | #
Ah ? Pourtant je fait bien : a / (b/c) ?
Citer : Posté le 09/06/2020 14:31 | #
Ah mais non !
1.0
Citer : Posté le 09/06/2020 14:34 | #
Donc la priorité c'est (a/b) / c
Il faut que je fasse un while
Ajouté le 09/06/2020 à 14:37 :
Du coup je décompose en multipliant par les inverses : a/b/c devient a * 1/b * 1/c
--- Tokens ---
('VAR', 'a')
('DIVI', '/')
('VAR', 'b')
('DIVI', '/')
('VAR', 'c')
--- AST ---
Operation : *
Variable : a
Operation : 1/
Variable : b
Operation : 1/
Variable : c
Citer : Posté le 09/06/2020 14:40 | #
Pour ton information, si tu as un symbole binaire (disons •) et que tu poses a•b•...•z = ((a•b)•...z), alors le symbole est dit associatif de gauche-à-droite.
À l'inverse, si tu poses que a•b•...•z = a•(b•(...z)), alors le symbole est dit associatif de droite-à-gauche.
Par exemple, l'exposant est associatif de droite-à-gauche, donc a**b**c = a**(b**c). Tous les autres opérateurs binaires usuels sont associatifs de gauche-à-droite, ce qui est le plus courant. Dans un parser comme celui que tu écris, qu'on appelle "à descente récursive", il faut faire des boucles pour manipuler les opérateurs qui sont associatifs de gauche-à-droite.
Ajouté le 09/06/2020 à 14:40 :
Oui parfait ! C'est le bon résultat !
Citer : Posté le 09/06/2020 14:44 | #
Okay ! Merci !!
Je pense m'arrêter là pour aujourd'hui
Citer : Posté le 09/06/2020 15:59 | #
À part le plus unaire qui est anecdotique, il manque surtout les appels de fonctions ! Qui sont un atome, donc sans trop spoiler je te laisse réfléchir à comment les ajouter.
Sinon oui, les conditions, ça se passera quasiment pareil. Je préfère parler d'"expressions booléennes" parce que tu vas voir qu'il y aussi des opérateurs binaires (et/ou), qu'ils ont des associativités (gauche-à-droite), un opérateur unaire (non), des parenthèses...
Citer : Posté le 09/06/2020 16:02 | #
J'ai pas trop compris le coup des appels de fonctions…
Okay pour "expression bouléennes" !
Citer : Posté le 09/06/2020 17:44 | #
Les appels de fonctions c'est les trucs comme f(x) !
Citer : Posté le 09/06/2020 17:50 | #
Ah oui ! Je les avaient oubliées x)
J'ai le droit de passer par une règle en plus ?
function_call -> VAR LPAR atome RPAR
Citer : Posté le 09/06/2020 17:57 | #
Tu as toujours le droit de rajouter des règles dans une grammaire !
Nooon ! Tu es tombé dans le piège facile !
Réfléchis bien à ce que tu as le droit de mettre entre les parenthèses.
Citer : Posté le 09/06/2020 17:59 | #
Ah ? x)
Bon ben faut réfléchir alors ?
Je peut mettre un nombre ou une variable, mais on peut bien imaginer mettre une expression arithmétique… ?
Citer : Posté le 09/06/2020 18:44 | #
Bien sûr qu'on peut imaginer une expression arithmétique ! Pourquoi limiter la forme de ce que tu peux mettre dans l'argument d'une fonction ?
C'est la spécialité du Basic Casio ça, tu as le droit d'écrire List 1 ou List N (avec N=1) mais tu ne peux pas écrire List (N+1). C'est chiant au possible !
Quand tu conçois ta grammaire, demande-toi toujours : quelle est la construction la plus générale que je peux autoriser ici ?
Citer : Posté le 09/06/2020 19:50 | #
Justement !
Citer : Posté le 09/06/2020 19:57 | #
Faux ! atome c'est tout petit. Comme je l'ai mentionné plusieurs fois, la construction la plus générale pour les expressions arithmétique c'est somme.
Pendant que j'y suis, tu devrais vraiment avoir un symbole arith_expr -> somme pour éviter de te poser la question à chaque fois et utiliser arith_expr à tous les endroits où tu peux mettre de l'arithmétique.
Citer : Posté le 10/06/2020 13:41 | #
Ah oui ok ! Je comprends
Pour le coup de expr c'est juste une fonction : def expr(self): return self.sum() ?
Citer : Posté le 10/06/2020 13:47 | #
Du coup oui, il suffit de faire ça.
Prends bien le temps de comprendre pourquoi somme est le plus général ici. Regarde comment dériver 1*a depuis atome ou depuis somme, par exemple.
Citer : Posté le 10/06/2020 13:59 | #
somme est plus général parce que j'ai cette hiérarchie : somme -> produit -> exposant -> atome
Citer : Posté le 10/06/2020 14:05 | #
Voilà c'est ça ! Une somme peut facilement devenir n'importe quel autre symbole arithmétique, donc c'est forcément la plus générale. atome c'est pas aussi général parce que si tu veux écrire 1*a tu es obligé de mettre des parenthèses !
Citer : Posté le 10/06/2020 14:07 | #
Du coup il me reste à implémenter la règle : function -> VAR LPAR expr RPAR !
Citer : Posté le 10/06/2020 14:16 | #
Et... n'oublie pas que les fonctions peuvent avoir plusieurs arguments !