1 # -*- coding: utf-8 -*-
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
24 def __init__(self,pere):
26 pere.l_objets.append(self)
28 def set_text(self,texte):
31 def append_text(self,texte):
33 Ajoute texte à self.texte en mettant un retour chariot à la fin de texte
36 self.texte = self.texte +texte
38 class COMMENTAIRE(ENTITE_JDC):
42 Retourne une chaîne de caractères représentants self
43 sous une forme interprétable par EFICAS
45 s='COMMENTAIRE("""'+self.texte+'""")\n\n'
48 def append_text(self,texte):
50 Ajoute texte à self.texte en enlevant le # initial
54 self.texte = self.texte+texte[1:]
56 # le dièse n'est pas sur le premier caractère
57 amont,aval = string.split(texte,'#',1) # on découpe suivant la première occurrence de #
58 self.texte = self.texte +amont + aval
60 class COMMANDE(ENTITE_JDC):
66 return self.texte+'\n'
70 Retourne la différence entre le nombre de parenthèses ouvrantes
71 et le nombre de parenthèses fermantes présentes dans self.texte
72 Peut donc retourner un entier négatif
74 # faire attention aux commentaires contenus dans self.texte
75 # qui peuvent eux-mêmes contenir des parenthèses !!!!
76 l_lignes = string.split(self.texte,'\n')
78 for ligne in l_lignes:
79 ligne = string.split(ligne,'#')[0]
80 nb = nb + (string.count(ligne,'(')-string.count(ligne,')'))
83 class AFFECTATION(ENTITE_JDC):
85 def append_text(self,texte):
87 Ajoute texte à self.texte en enlevant tout retour chariot et tout point virgule
89 if texte[-1] == '\n' : texte = string.strip(texte[0:-1])
\r
90 if texte[-1] == ';' : texte = string.strip(texte[0:-1])
91 self.texte = self.texte+texte
95 Retourne une expression de l'affectation compréhensible par ACCAS
96 et exploitable par EFICAS
98 nom,valeur = string.split(self.texte,'=',1)
99 nom = string.strip(nom)
100 if valeur[-1] == '\n': valeur = valeur[:-1]
101 valeur = string.strip(valeur)
108 return nom+' = PARAMETRE(nom=\''+nom+'\',valeur="'+valeur+'")\n\n'
110 class COMMANDE_COMMENTARISEE(ENTITE_JDC):
112 def append_text(self,texte):
114 Ajoute texte à self.texte en enlevant les doubles commentaires
116 texte = string.strip(texte)
117 texte = string.strip(texte[2:])
118 self.texte = self.texte+(len(self.texte)>0)*'\n'+texte
122 Retourne une expression de la commande commentarisée compréhensible par ACCAS
123 et exploitable par EFICAS
125 return "COMMANDE_COMM(texte='''"+self.texte+"''')\n"
127 class AFFECTATION_EVAL(ENTITE_JDC):
129 def append_text(self,texte):
131 Ajoute texte à self.texte en enlevant tout retour chariot
133 if texte[-1] == '\n' : texte = texte[1:-1]
134 self.texte = self.texte+texte
138 Retourne une expression du paramètre EVAL compréhensible par ACCAS
139 et exploitable par EFICAS
141 nom,valeur = string.split(self.texte,'=',1)
142 nom = string.strip(nom)
143 if valeur[-1] == '\n': valeur = valeur[:-1]
144 valeur = string.strip(valeur)
145 return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n'
147 class PARSEUR_PYTHON:
149 Cette classe sert à générer un objet PARSEUR_PYTHON qui réalise l'analyse d'un texte
150 représentant un JDC Python en distinguant :
151 - les commentaires inter commandes
155 pattern_commande = re.compile(r'^([A-Z][A-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)')
156 pattern_eval = re.compile(r'^(EVAL)([ \t\r\f\v]*)\(([\w\W]*)')
157 pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+')
159 def __init__(self,texte):
164 def is_affectation(self,texte):
166 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes
169 if '=' not in texte : return 0
170 if self.pattern_commande.match(texte):
171 # cas d'une procédure ...
173 amont,aval = string.split(texte,'=',1)
174 aval = string.strip(aval)
175 if self.pattern_commande.match(aval):
180 def is_eval(self,texte):
182 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL
183 dans un jeu de commandes Aster, 0 sinon
185 if '=' not in texte : return 0
186 if self.pattern_commande.match(texte):
187 # cas d'une procédure ...
189 amont,aval = string.split(texte,'=',1)
190 aval = string.strip(aval)
191 if not self.pattern_commande.match(aval) : return 0
192 if self.pattern_eval.match(aval):
197 def is_commande(self,texte):
199 Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes
202 if self.pattern_commande.match(texte):
203 # cas d'une procédure ...
205 # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' !
206 if '=' not in texte : return 0
207 # on a un texte de la forme xxxx = yyyyy
208 # --> reste à analyser yyyy
209 amont,aval = string.split(texte,'=',1)
210 aval = string.strip(aval)
211 if self.pattern_commande.match(aval):
218 Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
219 et de commentaires (parmi lesquels des instructions "commentarisées").
221 #AY##l_lignes = open(self.fichier,'r').readlines()
222 l_lignes = string.split(self.texte,'\n')
223 commentaire_courant = None
224 commande_courante = None
225 affectation_courante = None
226 commande_commentarisee_courante = None
229 for ligne in l_lignes :
231 if string.strip(ligne) == '':
232 # il s'agit d'un saut de ligne
236 liste = string.split(ligne,'##',1)
238 # on a trouvé un double commentaire dans la ligne
240 if string.strip(before) == '':
241 # il s'agit d'une commande commentarisée
242 if commentaire_courant :
243 commentaire_courant = None
244 elif commande_courante :
245 # on a un objet commentarisé à l'intérieur d'une commande
246 # --> non traité pour l'instant
247 commande_courante.append_text(ligne)
248 elif commande_commentarisee_courante :
249 # commande_commentarisee en cours : on ajoute la ligne
250 commande_commentarisee_courante.append_text(ligne)
252 # on crée un objet commande_commentarisee_courante
253 commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
254 commande_commentarisee_courante.append_text(ligne)
255 # si la ligne courante se termine par un ';', on décide - par hypothèse et peut-être à tort - que
256 # la commande commentarisée courante est terminée !!
257 if re.search( '; *$', ligne ) != None :
258 commande_commentarisee_courante = None
261 # on a un double commentaire en fin de ligne
262 # --> pour l'instant on ne fait rien
264 new_ligne = string.split(ligne,'#')[0] # on enlève toute la partie commentaire de la ligne
265 new_ligne = string.strip(new_ligne)
267 # la ligne n'est qu'un commentaire précédé d'éventuels blancs
268 if commande_courante :
269 # il s'agit d'un commentaire à l'intérieur d'une commande --> on ne fait rien
270 commande_courante.append_text(ligne)
271 elif commentaire_courant :
272 # il s'agit de la nième ligne d'un commentaire entre deux commandes
273 # --> on ajoute cette ligne au commentaire courant
274 commentaire_courant.append_text(ligne)
276 # il s'agit d'un commentaire entre deux commandes
277 # --> on le crée et il devient le commentaire courant
278 commentaire_courant = COMMENTAIRE(self)
279 commentaire_courant.append_text(ligne)
281 # la ligne contient des données autre qu'un éventuel commentaire
282 if commentaire_courant :
283 # on clôt un éventuel commentaire courant
284 commentaire_courant = None
285 if commande_courante :
286 commande_courante.append_text(ligne)
287 if commande_courante.get_nb_par() == 0:
288 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
290 self.analyse_reel(commande_courante.texte)
293 commande_courante = None
295 # il peut s'agir d'une commande ou d'une affectation ...
296 # ou de la poursuite d'une affectation !!!!!
298 if self.is_eval(new_ligne):
299 # --> affectation de type EVAL
300 if affectation_courante : affectation_courante = None
301 affectation = AFFECTATION_EVAL(self)
302 affectation.append_text(ligne)
303 elif self.is_affectation(new_ligne):
305 affectation_courante = AFFECTATION(self)
306 affectation_courante.append_text(ligne)
307 elif self.is_commande(new_ligne):
309 commande_courante = COMMANDE(self)
310 commande_courante.append_text(ligne)
311 affectation_courante = None
312 if commande_courante.get_nb_par() == 0:
313 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
314 self.analyse_reel(commande_courante.texte)
315 commande_courante = None
317 #--> poursuite d'une affectation
318 # PN -- pour Empecher une erreur pas propre
319 if affectation_courante != None :
320 affectation_courante.append_text(ligne)
321 #affectation_courante.append_text(ligne)
324 def enleve (self,texte) :
327 while (i<len(texte)):
328 if (texte[i] == " " or texte[i] == "\n" or texte[i] == "\t") :
331 chaine=chaine+texte[i]
335 def construit_genea(self,texte):
340 # traitement pour chaque caractere
341 while (indiceC < len(texte)):
343 if ( c == "," or c == "(" or c == ")"):
347 nouvelindice=indiceC+1
348 if texte[nouvelindice] != "(":
349 while ( texte[nouvelindice] != "," and texte[nouvelindice] != ")"):
350 valeur=valeur+texte[nouvelindice]
351 nouvelindice=nouvelindice+1
352 if nouvelindice == len(texte) :
353 nouvelindice=nouvelindice -1
355 if mot in self.appli.liste_simp_reel:
359 if str(clef) != str(valeur) :
360 dict_reel_concept[clef]=valeur
366 # s agit -il d un tuple
367 if texte[nouvelindice+1] != "(":
369 while ( texte[nouvelindice] != "="):
370 if texte[nouvelindice] == ")" :
374 nouvelindice=nouvelindice+1
375 if nouvelindice == len(texte) :
376 nouvelindice=nouvelindice -1
379 valeur=texte[indiceC+1:nouvelindice+1]
380 indiceC=nouvelindice+1
381 if mot in self.appli.liste_simp_reel:
383 for val in valeur.split(',') :
384 # Attention la derniere valeur est""
388 if str(clef) != str(val) :
389 dict_reel_concept[clef]=val
397 mot=mot+texte[indiceC]
399 # traitement du dernier inutile
401 return dict_reel_concept
403 def analyse_reel(self,commande) :
405 # On verifie qu on a bien un OPER
407 if commande.find("=") > commande.find("(") :
409 if commande.find("=") > 0:
410 epure1=self.enleve(commande)
411 nomConcept=epure1.split("=")[0]
412 index=epure1.find("=")
413 epure2=epure1[index+1:len(epure1)].replace("_F(","(")
414 dict_reel_concept=self.construit_genea(epure2)
415 if nomConcept !=None :
416 if len(dict_reel_concept) != 0:
417 self.appli.dict_reels[nomConcept]=dict_reel_concept
419 def get_texte(self,appli=None):
421 Retourne le texte issu de l'analyse
424 if not self.l_objets : self.analyse()
426 for obj in self.l_objets:
430 if __name__ == "__main__" :
431 #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
432 fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
433 texte = open(fichier,'r').read()
434 txt = PARSEUR_PYTHON(texte).get_texte()