3 import string,traceback
5 from I_MACRO_ETAPE import MACRO_ETAPE
6 from Extensions import interpreteur_formule
7 from Editeur import analyse_catalogue
9 analyse_catalogue.l_noms_commandes.append('FORM') # déclare le nom FORM à l'analyseur de catalogue
12 class FORM_ETAPE(MACRO_ETAPE):
14 interpreteur = interpreteur_formule.Interpreteur_Formule
17 self.mc_liste=self.build_mc()
18 # on crée la liste des types autorisés (liste des noms de mots-clés
19 # simples dans le catalogue de FORMULE)
20 self.l_types_autorises = self.definition.entites.keys()
21 # en plus de la construction traditionnelle des fils de self
22 # il faut pour les FORMULE décortiquer l'expression ...
23 self.type_retourne,self.arguments,self.corps = self.analyse_formule()
25 def analyse_formule(self):
27 Cette méthode décortique l'expression de la FORMULE.
28 Elle retourne 3 valeurs:
29 - le type retourné par la FORMULE
30 - les arguments de la FORMULE
31 - le corps de la FORMULE, cad son expression
33 if len(self.mc_liste) == 0:
34 # pas de fils pour self --> la FORMULE est incomplète
36 child = self.mc_liste[0] # child est un MCSIMP
37 type_retourne = child.definition.nom
38 valeur = child.getval()
39 # c'est dans valeur que se trouvent la liste des arguments et le corps de la fonction
41 l_args,corps = string.split(valeur,'=',1)
43 # pas de signe = --> la formule est fausse
44 return type_retourne,None,None
45 l_args = string.strip(l_args)
46 corps = string.strip(corps)
47 return type_retourne,l_args,corps
51 Retourne le nom de la FORMULE, cad le nom de la SD si elle existe,
55 return self.sd.get_name()
59 def get_formule(self):
61 Retourne un tuple décrivant la formule :
62 (nom,type_retourne,arguments,corps)
64 t,a,c = self.analyse_formule()
68 def verif_arguments(self,arguments = None):
70 Vérifie si les arguments passés en argument (si aucun prend les arguments courants)
71 sont des arguments valide pour une FORMULE.
73 - un booléen, qui vaut 1 si arguments licites, 0 sinon
74 - un message d'erreurs ('' si illicites)
77 arguments = self.arguments
79 return 0,"Une formule doit avoir au minimum un argument"
80 # il faut au préalable enlever les parenthèses ouvrantes et fermantes
81 # encadrant les arguments
82 arguments = string.strip(arguments)
83 if arguments[0] != '(':
84 return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse ouvrante manquante"
85 if arguments[-1] != ')':
86 return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse fermante manquante"
87 # on peut tester la syntaxe de chaque argument maintenant
90 arguments = arguments[1:-1] # on enlève les parenthèses ouvrante et fermante
91 l_arguments = string.split(arguments,',')
92 for argument in l_arguments:
93 argument = string.strip(argument)
95 typ,nom = string.split(argument,':')
96 # pas de vérification sur le nom de l'argument
97 # vérification du type de l'argument
98 typ = string.strip(typ)
99 if typ not in self.l_types_autorises :
101 erreur = erreur + "Le type "+typ+" n'est pas un type permis pour "+nom+'\n'
103 # l'argument ne respecte pas la syntaxe : typ_arg : nom_arg
105 erreur = erreur+"Syntaxe argument non valide : "+argument+'\n'
108 def verif_corps(self,corps=None,arguments=None):
110 Cette méthode a pour but de vérifier si le corps de la FORMULE
111 est syntaxiquement correct.
113 - un booléen, qui vaut 1 si corps de FORMULE licite, 0 sinon
114 - un message d'erreurs ('' si illicite)
119 arguments = self.arguments
120 formule=(self.get_nom(),self.type_retourne,arguments,corps)
121 # on récupère la liste des constantes et des autres fonctions prédéfinies
122 # et qui peuvent être utilisées dans le corps de la formule courante
123 l_ctes,l_form = self.jdc.get_parametres_fonctions_avant_etape(self)
124 # on crée un objet vérificateur
126 verificateur = self.interpreteur(formule=formule,
130 traceback.print_exc()
131 return 0,"Impossible de réaliser la vérification de la formule"
132 return verificateur.isvalid(),verificateur.report()
134 def verif_nom(self,nom=None):
136 Vérifie si le nom passé en argument (si aucun prend le nom courant)
137 est un nom valide pour une FORMULE.
139 - un booléen, qui vaut 1 si nom licite, 0 sinon
140 - un message d'erreurs ('' si illicite)
145 return 0,"Pas de nom donné à la FORMULE"
147 return 0,"Un nom de FORMULE ne peut dépasser 8 caractères"
148 sd = self.parent.get_sd_autour_etape(nom,self)
150 return 0,"Un concept de nom %s existe déjà !" %nom
153 def verif_type(self,type=None):
155 Vérifie si le type passé en argument (si aucun prend le type courant)
156 est un type valide pour une FORMULE.
158 - un booléen, qui vaut 1 si type licite, 0 sinon
159 - un message d'erreurs ('' si illicite)
162 type = self.type_retourne
164 return 0,"Le type de la valeur retournée n'est pas spécifié"
165 if type not in self.l_types_autorises:
166 return 0,"Une formule ne peut retourner une valeur de type : %s" %type
169 def verif_formule(self,formule=None):
171 Vérifie la validité de la formule passée en argument.
172 Cette nouvelle formule est passée sous la forme d'un tuple :
173 (nom,type_retourne,arguments,corps)
174 Si aucune formule passée, prend les valeurs courantes de la formule
176 - un booléen, qui vaut 1 si formule licite, 0 sinon
177 - un message d'erreurs ('' si illicite)
180 formule = (None,None,None,None)
181 test_nom,erreur_nom = self.verif_nom(formule[0])
182 test_type,erreur_type = self.verif_type(formule[1])
184 args = '('+formule[2]+')'
187 test_arguments,erreur_arguments = self.verif_arguments(args)
188 test_corps,erreur_corps = self.verif_corps(corps = formule[3], arguments = args)
189 # test global = produit des tests partiels
190 test = test_nom*test_type*test_arguments*test_corps
191 # message d'erreurs global = concaténation des messages partiels
194 for mess in (erreur_nom,erreur_type,erreur_arguments,erreur_corps):
195 erreur = erreur+(len(mess) > 0)*'\n'+mess
198 def update(self,formule):
201 Met à jour les champs nom, type_retourne,arguments et corps de la FORMULE
202 par les nouvelles valeurs passées dans le tuple formule.
203 On stocke les valeurs SANS vérifications.
206 self.type_retourne = formule[1]
207 self.arguments = '('+formule[2]+')'
208 self.corps = formule[3]
209 # il faut ajouter le mot-clé simple correspondant dans mc_liste
210 # pour cela on utilise la méthode générale build_mc
211 # du coup on est obligé de modifier le dictionnaire valeur de self ...
213 self.valeur[self.type_retourne] = self.arguments+' = ' + self.corps
215 sd = self.get_sd_prod()
221 Rend l'etape courante active.
222 Il faut ajouter la formule au contexte global du JDC
226 if nom == '' : return
228 self.jdc.append_fonction(self.sd)
234 Rend l'etape courante inactive
235 Il faut supprimer la formule du contexte global du JDC
238 if not self.sd : return
239 self.jdc.del_fonction(self.sd)
241 def delete_concept(self,sd):
246 Mettre a jour les mos cles de l etape et eventuellement le concept produit si reuse
247 suite à la disparition du concept sd
248 Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils,
249 sauf les objets FORM_ETAPE qui doivent vérifier que le concept détruit n'est pas
250 utilisé dans le corps de la fonction