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):
163 def is_affectation(self,texte):
165 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes
168 if '=' not in texte : return 0
169 if self.pattern_commande.match(texte):
170 # cas d'une procédure ...
172 amont,aval = string.split(texte,'=',1)
173 aval = string.strip(aval)
174 if self.pattern_commande.match(aval):
179 def is_eval(self,texte):
181 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL
182 dans un jeu de commandes Aster, 0 sinon
184 if '=' not in texte : return 0
185 if self.pattern_commande.match(texte):
186 # cas d'une procédure ...
188 amont,aval = string.split(texte,'=',1)
189 aval = string.strip(aval)
190 if not self.pattern_commande.match(aval) : return 0
191 if self.pattern_eval.match(aval):
196 def is_commande(self,texte):
198 Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes
201 if self.pattern_commande.match(texte):
202 # cas d'une procédure ...
204 # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' !
205 if '=' not in texte : return 0
206 # on a un texte de la forme xxxx = yyyyy
207 # --> reste à analyser yyyy
208 amont,aval = string.split(texte,'=',1)
209 aval = string.strip(aval)
210 if self.pattern_commande.match(aval):
217 Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
218 et de commentaires (parmi lesquels des instructions "commentarisées").
220 #AY##l_lignes = open(self.fichier,'r').readlines()
221 l_lignes = string.split(self.texte,'\n')
222 commentaire_courant = None
223 commande_courante = None
224 affectation_courante = None
225 commande_commentarisee_courante = None
228 for ligne in l_lignes :
230 if string.strip(ligne) == '':
231 # il s'agit d'un saut de ligne
235 liste = string.split(ligne,'##',1)
237 # on a trouvé un double commentaire dans la ligne
239 if string.strip(before) == '':
240 # il s'agit d'une commande commentarisée
241 if commentaire_courant :
242 commentaire_courant = None
243 elif commande_courante :
244 # on a un objet commentarisé à l'intérieur d'une commande
245 # --> non traité pour l'instant
246 commande_courante.append_text(ligne)
247 elif commande_commentarisee_courante :
248 # commande_commentarisee en cours : on ajoute la ligne
249 commande_commentarisee_courante.append_text(ligne)
251 # on crée un objet commande_commentarisee_courante
252 commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
253 commande_commentarisee_courante.append_text(ligne)
254 # si la ligne courante se termine par un ';', on décide - par hypothèse et peut-être à tort - que
255 # la commande commentarisée courante est terminée !!
256 if re.search( '; *$', ligne ) != None :
257 commande_commentarisee_courante = None
260 # on a un double commentaire en fin de ligne
261 # --> pour l'instant on ne fait rien
263 new_ligne = string.split(ligne,'#')[0] # on enlève toute la partie commentaire de la ligne
264 new_ligne = string.strip(new_ligne)
266 # la ligne n'est qu'un commentaire précédé d'éventuels blancs
267 if commande_courante :
268 # il s'agit d'un commentaire à l'intérieur d'une commande --> on ne fait rien
269 commande_courante.append_text(ligne)
270 elif commentaire_courant :
271 # il s'agit de la nième ligne d'un commentaire entre deux commandes
272 # --> on ajoute cette ligne au commentaire courant
273 commentaire_courant.append_text(ligne)
275 # il s'agit d'un commentaire entre deux commandes
276 # --> on le crée et il devient le commentaire courant
277 commentaire_courant = COMMENTAIRE(self)
278 commentaire_courant.append_text(ligne)
280 # la ligne contient des données autre qu'un éventuel commentaire
281 if commentaire_courant :
282 # on clôt un éventuel commentaire courant
283 commentaire_courant = None
284 if commande_courante :
285 commande_courante.append_text(ligne)
286 if commande_courante.get_nb_par() == 0:
287 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
288 commande_courante = None
290 # il peut s'agir d'une commande ou d'une affectation ...
291 # ou de la poursuite d'une affectation !!!!!
293 if self.is_eval(new_ligne):
294 # --> affectation de type EVAL
295 if affectation_courante : affectation_courante = None
296 affectation = AFFECTATION_EVAL(self)
297 affectation.append_text(ligne)
298 elif self.is_affectation(new_ligne):
300 affectation_courante = AFFECTATION(self)
301 affectation_courante.append_text(ligne)
302 elif self.is_commande(new_ligne):
304 commande_courante = COMMANDE(self)
305 commande_courante.append_text(ligne)
306 affectation_courante = None
307 if commande_courante.get_nb_par() == 0:
308 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
309 commande_courante = None
311 #--> poursuite d'une affectation
312 # PN -- pour Empecher une erreur pas propre
313 if affectation_courante != None :
314 affectation_courante.append_text(ligne)
315 #affectation_courante.append_text(ligne)
320 Retourne le texte issu de l'analyse
322 if not self.l_objets : self.analyse()
324 for obj in self.l_objets:
328 if __name__ == "__main__" :
329 #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
330 fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
331 texte = open(fichier,'r').read()
332 txt = PARSEUR_PYTHON(texte).get_texte()