1 # CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
23 def __init__(self,pere):
25 pere.l_objets.append(self)
27 def set_text(self,texte):
30 def append_text(self,texte):
32 Ajoute texte à self.texte en mettant un retour chariot à la fin de texte
35 self.texte = self.texte +texte
37 class COMMENTAIRE(ENTITE_JDC):
41 Retourne une chaîne de caractères représentants self
42 sous une forme interprétable par EFICAS
44 s='COMMENTAIRE("""'+self.texte+'""")\n\n'
47 def append_text(self,texte):
49 Ajoute texte à self.texte en enlevant le # initial
53 self.texte = self.texte+texte[1:]
55 # le dièse n'est pas sur le premier caractère
56 amont,aval = string.split(texte,'#',1) # on découpe suivant la première occurrence de #
57 self.texte = self.texte +amont + aval
59 class COMMANDE(ENTITE_JDC):
65 return self.texte+'\n'
69 Retourne la différence entre le nombre de parenthèses ouvrantes
70 et le nombre de parenthèses fermantes présentes dans self.texte
71 Peut donc retourner un entier négatif
73 # faire attention aux commentaires contenus dans self.texte
74 # qui peuvent eux-mêmes contenir des parenthèses !!!!
75 l_lignes = string.split(self.texte,'\n')
77 for ligne in l_lignes:
78 ligne = string.split(ligne,'#')[0]
79 nb = nb + (string.count(ligne,'(')-string.count(ligne,')'))
82 class AFFECTATION(ENTITE_JDC):
84 def append_text(self,texte):
86 Ajoute texte à self.texte en enlevant tout retour chariot et tout point virgule
88 if texte[-1] == '\n' : texte = string.strip(texte[0:-1])
\r
89 if texte[-1] == ';' : texte = string.strip(texte[0:-1])
90 self.texte = self.texte+texte
94 Retourne une expression de l'affectation compréhensible par ACCAS
95 et exploitable par EFICAS
97 nom,valeur = string.split(self.texte,'=',1)
98 nom = string.strip(nom)
99 if valeur[-1] == '\n': valeur = valeur[:-1]
100 valeur = string.strip(valeur)
101 return nom+' = PARAMETRE(nom=\''+nom+'\',valeur="'+valeur+'")\n\n'
103 class COMMANDE_COMMENTARISEE(ENTITE_JDC):
105 def append_text(self,texte):
107 Ajoute texte à self.texte en enlevant les doubles commentaires
109 texte = string.strip(texte)
110 texte = string.strip(texte[2:])
111 self.texte = self.texte+(len(self.texte)>0)*'\n'+texte
115 Retourne une expression de la commande commentarisée compréhensible par ACCAS
116 et exploitable par EFICAS
118 return "COMMANDE_COMM(texte='''"+self.texte+"''')\n"
120 class AFFECTATION_EVAL(ENTITE_JDC):
122 def append_text(self,texte):
124 Ajoute texte à self.texte en enlevant tout retour chariot
126 if texte[-1] == '\n' : texte = texte[1:-1]
127 self.texte = self.texte+texte
131 Retourne une expression du paramètre EVAL compréhensible par ACCAS
132 et exploitable par EFICAS
134 nom,valeur = string.split(self.texte,'=',1)
135 nom = string.strip(nom)
136 if valeur[-1] == '\n': valeur = valeur[:-1]
137 valeur = string.strip(valeur)
138 return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n'
140 class PARSEUR_PYTHON:
142 Cette classe sert à générer un objet PARSEUR_PYTHON qui réalise l'analyse d'un texte
143 représentant un JDC Python en distinguant :
144 - les commentaires inter commandes
148 pattern_commande = re.compile(r'^([A-Z][A-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)')
149 pattern_eval = re.compile(r'^(EVAL)([ \t\r\f\v]*)\(([\w\W]*)')
150 pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+')
152 def __init__(self,texte):
156 def is_affectation(self,texte):
158 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes
161 if '=' not in texte : return 0
162 if self.pattern_commande.match(texte):
163 # cas d'une procédure ...
165 amont,aval = string.split(texte,'=',1)
166 aval = string.strip(aval)
167 if self.pattern_commande.match(aval):
172 def is_eval(self,texte):
174 Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL
175 dans un jeu de commandes Aster, 0 sinon
177 if '=' not in texte : return 0
178 if self.pattern_commande.match(texte):
179 # cas d'une procédure ...
181 amont,aval = string.split(texte,'=',1)
182 aval = string.strip(aval)
183 if not self.pattern_commande.match(aval) : return 0
184 if self.pattern_eval.match(aval):
189 def is_commande(self,texte):
191 Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes
194 if self.pattern_commande.match(texte):
195 # cas d'une procédure ...
197 # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' !
198 if '=' not in texte : return 0
199 # on a un texte de la forme xxxx = yyyyy
200 # --> reste à analyser yyyy
201 amont,aval = string.split(texte,'=',1)
202 aval = string.strip(aval)
203 if self.pattern_commande.match(aval):
210 Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
211 et de commentaires (parmi lesquels des instructions "commentarisées").
213 #AY##l_lignes = open(self.fichier,'r').readlines()
214 l_lignes = string.split(self.texte,'\n')
215 commentaire_courant = None
216 commande_courante = None
217 affectation_courante = None
218 commande_commentarisee_courante = None
221 for ligne in l_lignes :
223 if string.strip(ligne) == '':
224 # il s'agit d'un saut de ligne
228 liste = string.split(ligne,'##',1)
230 # on a trouvé un double commentaire dans la ligne
232 if string.strip(before) == '':
233 # il s'agit d'une commande commentarisée
234 if commentaire_courant :
235 commentaire_courant = None
236 elif commande_courante :
237 # on a un objet commentarisé à l'intérieur d'une commande
238 # --> non traité pour l'instant
239 commande_courante.append_text(ligne)
240 elif commande_commentarisee_courante :
241 # commande_commentarisee en cours : on ajoute la ligne
242 commande_commentarisee_courante.append_text(ligne)
244 # on crée un objet commande_commentarisee_courante
245 commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
246 commande_commentarisee_courante.append_text(ligne)
247 # si la ligne courante se termine par un ';', on décide - par hypothèse et peut-être à tort - que
248 # la commande commentarisée courante est terminée !!
249 if re.search( '; *$', ligne ) != None :
250 commande_commentarisee_courante = None
253 # on a un double commentaire en fin de ligne
254 # --> pour l'instant on ne fait rien
256 new_ligne = string.split(ligne,'#')[0] # on enlève toute la partie commentaire de la ligne
257 new_ligne = string.strip(new_ligne)
259 # la ligne n'est qu'un commentaire précédé d'éventuels blancs
260 if commande_courante :
261 # il s'agit d'un commentaire à l'intérieur d'une commande --> on ne fait rien
262 commande_courante.append_text(ligne)
263 elif commentaire_courant :
264 # il s'agit de la nième ligne d'un commentaire entre deux commandes
265 # --> on ajoute cette ligne au commentaire courant
266 commentaire_courant.append_text(ligne)
268 # il s'agit d'un commentaire entre deux commandes
269 # --> on le crée et il devient le commentaire courant
270 commentaire_courant = COMMENTAIRE(self)
271 commentaire_courant.append_text(ligne)
273 # la ligne contient des données autre qu'un éventuel commentaire
274 if commentaire_courant :
275 # on clôt un éventuel commentaire courant
276 commentaire_courant = None
277 if commande_courante :
278 commande_courante.append_text(ligne)
279 if commande_courante.get_nb_par() == 0:
280 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
281 commande_courante = None
283 # il peut s'agir d'une commande ou d'une affectation ...
284 # ou de la poursuite d'une affectation !!!!!
286 if self.is_eval(new_ligne):
287 # --> affectation de type EVAL
288 if affectation_courante : affectation_courante = None
289 affectation = AFFECTATION_EVAL(self)
290 affectation.append_text(ligne)
291 elif self.is_affectation(new_ligne):
293 affectation_courante = AFFECTATION(self)
294 affectation_courante.append_text(ligne)
295 elif self.is_commande(new_ligne):
297 commande_courante = COMMANDE(self)
298 commande_courante.append_text(ligne)
299 affectation_courante = None
300 if commande_courante.get_nb_par() == 0:
301 # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
302 commande_courante = None
304 #--> poursuite d'une affectation
305 affectation_courante.append_text(ligne)
310 Retourne le texte issu de l'analyse
312 if not self.l_objets : self.analyse()
314 for obj in self.l_objets:
318 if __name__ == "__main__" :
319 #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
320 fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
321 texte = open(fichier,'r').read()
322 txt = PARSEUR_PYTHON(texte).get_texte()