Salome HOME
aa4a5d430f56f2272da330ddff666f9e72e96054
[tools/eficas.git] / convert / parseur_python.py
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.
9 #
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.
14 #
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.
18 #
19 #
20 # ======================================================================
21 import sys,string,re
22 import traceback
23
24 escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
25 stringsAndCommentsRE =  \
26       re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
27 allchars = string.maketrans("", "")
28 allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
29 allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
30
31 def maskStringsAndComments(src):
32     """Masque tous les caracteres de src contenus dans des commentaires ou des strings multilignes (triples
33        quotes et guillemets.
34        Le masquage est realise en remplacant les caracteres par des * 
35        Attention : cette fonction doit etre utilisee sur un texte complet et pas ligne par ligne
36     """
37     src = escapedQuotesRE.sub("**", src)
38     allstrings = stringsAndCommentsRE.split(src)
39     # every odd element is a string or comment
40     for i in xrange(1, len(allstrings), 2):
41         if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
42             allstrings[i] = allstrings[i][:3]+ \
43                            allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
44                            allstrings[i][-3:]
45         else:
46             allstrings[i] = allstrings[i][0]+ \
47                            allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
48                            allstrings[i][-1]
49
50     return "".join(allstrings)
51
52 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
53 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
54 emptyHangingBraces = [0,0,0,0,0]
55
56 class ParserException(Exception): pass
57 class FatalError(Exception): pass
58
59 #commentaire double precede d'un nombre quelconque de blancs (pas multiligne)
60 pattern_2comments   = re.compile(r"^\s*##.*")
61 #commentaire standard precede d'un nombre quelconque de blancs (pas multiligne)
62 pattern_comment   = re.compile(r"^\s*#.*")
63 #fin de ligne ; suivi d'un nombre quelconque de blancs (pas multiligne)
64 pattern_fin   = re.compile(r"; *$")
65 #pattern pour supprimer les blancs, tabulations et fins de ligne
66 pattern_blancs = re.compile(r"[ \t\r\f\v]")
67 #pattern_blancs = re.compile(r"[\s\n]")
68 number_kw_pattern=re.compile(r"""
69 (
70     #groupe nombre decimal
71     (?:
72         #signe : on ignore le signe +
73         [-]?
74         #groupe (avec ?: n'apparait pas en tant que groupe dans le resultat)
75         (?:
76             #mantisse forme entiere.fractionnaire
77             \d+(?:\.\d*)?
78             |
79             #ou forme .fractionnaire
80             \.\d+
81         )
82         (?:[eE][+-]?\d+)?
83     )
84     |
85     #argument keyword
86     [a-zA-Z_]\w*=
87 )
88 """,re.VERBOSE|re.MULTILINE)
89
90 def construit_genea(texte,liste_mc):
91     """Retourne un dictionnaire dont les cles sont des reels et les valeurs sont leurs representations textuelles.
92        Realise un filtrage sur les reels :
93          - Ne garde que les reels pour lesquels str ne donne pas une bonne representation.
94          - Ne garde que les reels derriere un argument keyword dont le nom est dans liste_mc
95     >>> s = '''a=+21.3e-5*85,b=-.1234,c=81.6   , d= -8 , e=_F(x=342.67,y=-1), f=+1.1, g=(1.3,-5,1.54E-3),
96     ... #POMPE_PRIMA._BOUCLE_N._2_ELEMENT_NUMERO:0239
97     ... h=_F(x=34.6,y=-1)'''
98     >>> construit_genea(s,['a','x'])
99     {0.000213: '21.3e-5'}
100     """
101     d={}
102     mot=""
103     #on masque les strings et commentaires pour ne pas identifier de faux reels
104     for m in number_kw_pattern.findall(maskStringsAndComments(texte)):
105         if m[-1] == '=':
106             #argument keyword
107             mot=m[:-1]
108         else:
109             if mot not in liste_mc:continue
110             #valeur
111             key=eval(m)
112             if str(key) != m: d[key]=m
113     return d
114
115
116 class ENTITE_JDC :
117     """Classe de base pour tous les objets créés lors de la conversion
118        Tout objet dérivé est enregistré auprès de son père à sa création
119     """
120     def __init__(self,pere):
121         self.texte = ''
122         pere.l_objets.append(self)
123
124     def set_text(self,texte):
125         self.texte = texte
126
127     def append_text(self,texte):
128         """
129         Ajoute texte à self.texte en mettant un retour chariot à la fin de texte
130         """
131         texte = texte+'\n'
132         self.texte = self.texte +texte
133
134     def __str__(self):
135         return self.texte
136
137 class COMMENTAIRE(ENTITE_JDC):
138
139     def __str__(self):
140         """
141         Retourne une chaîne de caractères représentants self
142         sous une forme interprétable par EFICAS
143         """
144         t=repr(self.texte)
145         return "COMMENTAIRE("+t+")\n"
146
147         #s='COMMENTAIRE("""'+self.texte+'""")\n\n'
148         #return s
149
150     def append_text(self,texte):
151         """
152         Ajoute texte à self.texte en enlevant le # initial
153         """
154         texte = texte+'\n'
155         if texte[0] == '#':
156             self.texte = self.texte+texte[1:]
157         else:
158             # le dièse n'est pas sur le premier caractère
159             amont,aval = string.split(texte,'#',1) # on découpe suivant la première occurrence de #
160             self.texte = self.texte +amont + aval
161         
162 class COMMANDE(ENTITE_JDC):
163
164     def __str__(self):
165         """
166         Retourne self.texte
167         """
168         return self.texte+'\n'
169         
170     def get_nb_par(self):
171         """
172         Retourne la différence entre le nombre de parenthèses ouvrantes
173         et le nombre de parenthèses fermantes présentes dans self.texte
174         Peut donc retourner un entier négatif
175         """
176         # faire attention aux commentaires contenus dans self.texte
177         # qui peuvent eux-mêmes contenir des parenthèses !!!!
178         l_lignes = string.split(self.texte,'\n')
179         nb = 0
180         for ligne in l_lignes:
181             ligne = string.split(ligne,'#')[0]
182             nb = nb + (string.count(ligne,'(')-string.count(ligne,')'))
183         return nb
184
185 class AFFECTATION(ENTITE_JDC):
186
187     def append_text(self,texte):
188         """
189         Ajoute texte à self.texte en enlevant tout retour chariot et tout point virgule
190         PN et tout commentaire
191         """
192         if texte[-1] == '\n' : texte = string.rstrip(texte[0:-1])
193         if texte[-1] == ';' : texte = string.rstrip(texte[0:-1])
194         self.texte = self.texte+texte+'\n'
195         
196     def __str__(self):
197         """
198         Retourne une expression de l'affectation compréhensible par ACCAS
199         et exploitable par EFICAS
200         """
201         nom,valeur = string.split(self.texte,'=',1)
202         n = string.rstrip(nom)
203         nom = string.lstrip(n)
204         if valeur[-1] == '\n': valeur = valeur[:-1]
205         return n + ' = PARAMETRE(nom=\''+nom+'\',valeur='+valeur+')\n'
206
207 class COMMANDE_COMMENTARISEE(ENTITE_JDC):
208
209     def append_text(self,texte):
210         """
211         Ajoute texte à self.texte en enlevant les doubles commentaires
212         """
213         texte = string.strip(texte)
214         texte = string.strip(texte[2:])
215         self.texte = self.texte+(len(self.texte)>0)*'\n'+texte
216
217     def __str__(self):
218         """
219         Retourne une expression de la commande commentarisée compréhensible par ACCAS
220         et exploitable par EFICAS
221         """
222         return "COMMANDE_COMM(texte="+repr(self.texte)+")\n"
223         #return "COMMANDE_COMM(texte='''"+self.texte+"''')\n"
224
225 class AFFECTATION_EVAL(ENTITE_JDC):
226
227     def append_text(self,texte):
228         """
229         Ajoute texte à self.texte en enlevant tout retour chariot
230         """
231         if texte[-1] == '\n' : texte = texte[1:-1]
232         self.texte = self.texte+texte
233         
234     def __str__(self):
235         """
236         Retourne une expression du paramètre EVAL compréhensible par ACCAS
237         et exploitable par EFICAS
238         """
239         nom,valeur = string.split(self.texte,'=',1)
240         nom = string.strip(nom)
241         if valeur[-1] == '\n': valeur = valeur[:-1]
242         valeur = string.strip(valeur)
243         return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n'
244         
245 class PARSEUR_PYTHON:
246     """
247     Cette classe sert à générer un objet PARSEUR_PYTHON qui réalise l'analyse d'un texte 
248     représentant un JDC Python en distinguant :
249       - les commentaires inter commandes
250       - les affectations
251       - les commandes
252     """
253     pattern_commande   = re.compile(r'^([A-Z][A-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)')
254     pattern_eval       = re.compile(r'^(EVAL)([ \t\r\f\v]*)\(([\w\W]*)')
255     pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+')
256     pattern_name       = re.compile(r'[a-zA-Z_]\w*')
257     
258     def __init__(self,texte):
259         self.texte = texte
260         self.l_objets=None
261         self.appli=None
262
263     def is_affectation(self,texte):
264         """
265         Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes
266         Aster, 0 sinon
267         """
268         if '=' not in texte : return 0
269         if self.pattern_commande.match(texte):
270             # cas d'une procédure ...
271             return 0
272         amont,aval = string.split(texte,'=',1)
273         aval = string.strip(aval)
274         if self.pattern_commande.match(aval):
275             return 0
276         else:
277             s= string.strip(amont)
278             m= self.pattern_name.match(s)
279             if m is None : return 0
280             if m.start() != 0 :return 0
281             if m.end() != len(s):return 0
282             #print texte,amont,aval
283             return 1
284
285     def is_eval(self,texte):
286         """
287         Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL
288         dans un jeu de commandes Aster, 0 sinon
289         """
290         if '=' not in texte : return 0
291         if self.pattern_commande.match(texte):
292             # cas d'une procédure ...
293             return 0
294         amont,aval = string.split(texte,'=',1)
295         aval = string.strip(aval)
296         if not self.pattern_commande.match(aval) : return 0
297         if self.pattern_eval.match(aval):
298             return 1
299         else:
300             return 0
301             
302     def is_commande(self,texte):
303         """
304         Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes
305         Aster, 0 sinon
306         """
307         if self.pattern_commande.match(texte):
308             # cas d'une procédure ...
309             return 1
310         # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' !
311         if '=' not in texte : return 0
312         # on a un texte de la forme xxxx = yyyyy
313         # --> reste à analyser yyyy
314         amont,aval = string.split(texte,'=',1)
315         aval = string.strip(aval)
316         if self.pattern_commande.match(aval):
317             return 1
318         else:
319             return 0
320
321     def analyse(self):
322         """
323         Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
324         et de commentaires (parmi lesquels des instructions "commentarisées").
325         """
326         l_lignes = string.split(self.texte,'\n')
327         commentaire_courant             = None
328         commande_courante               = None
329         affectation_courante            = None
330         commande_commentarisee_courante = None
331         self.l_objets = []
332
333         #initialisation du nombre de parentheses non fermees et de commentaires non termines
334         #Attention a reinitialiser en fin de ligne logique
335         #Une ligne logique peut s'etendre sur plusieurs lignes physiques avec des caracteres de continuation
336         #explicites ou implicites
337         hangingBraces = list(emptyHangingBraces)
338         hangingComments = 0
339
340         #Masquage des commentaires et strings multilignes
341         srcMasked=maskStringsAndComments('\n'.join(l_lignes))
342         #print srcMasked
343         masked_lines=srcMasked.split('\n')
344         lineno=0
345
346         for ligne in l_lignes :
347             line=masked_lines[lineno]
348             lineno=lineno+1
349             #print "ligne:",line
350             # mise a jour du nombre total de parentheses ouvertes (non fermees)
351             # et du nombre de commentaires non termines
352             for i in range(len(implicitContinuationChars)):
353                 contchar = implicitContinuationChars[i]
354                 numHanging = hangingBraces[i]
355                 hangingBraces[i] = numHanging+line.count(contchar[0]) - line.count(contchar[1])
356
357             hangingComments ^= line.count('"""') % 2
358             hangingComments ^= line.count("'''") % 2
359             #print hangingComments,hangingBraces
360             if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0: 
361                 raise ParserException()
362
363             if string.strip(ligne) == '':
364                 # il s'agit d'un saut de ligne
365                 # --> on l'ignore
366                 continue
367
368             if pattern_2comments.match(ligne):
369                 #on a trouvé une commande commentarisée : double commentaire sans rien devant à part des blancs
370                 if commentaire_courant:
371                     #Si un commentaire ordinaire est en cours on le termine
372                     commentaire_courant = None
373
374                 if commande_courante :
375                     # on a un objet commentarisé à l'intérieur d'une commande
376                     # --> non traité pour l'instant : on l'ajoute simplement a la commande courante comme
377                     # un commentaire ordinaire
378                     commande_courante.append_text(ligne)
379                 elif commande_commentarisee_courante :
380                     # commande_commentarisee en cours : on ajoute la ligne
381                     commande_commentarisee_courante.append_text(ligne)
382                 else:
383                     # debut de commande commentarisée : on crée un objet commande_commentarisee_courante
384                     commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
385                     commande_commentarisee_courante.append_text(ligne)
386
387                 #on passe à la ligne suivante
388                 continue
389
390             if pattern_comment.match(ligne):
391                 #commentaire ordinaire avec seulement des blancs devant
392                 if commande_commentarisee_courante :
393                     # commande_commentarisee en cours : on la clot
394                     commande_commentarisee_courante = None
395
396                 if commande_courante :
397                     # il s'agit d'un commentaire à l'intérieur d'une commande --> on ne fait rien de special
398                     #on l'ajoute au texte de la commande 
399                     commande_courante.append_text(ligne)
400                 elif commentaire_courant :
401                     # il s'agit de la nième ligne d'un commentaire entre deux commandes
402                     # --> on ajoute cette ligne au commentaire courant
403                     commentaire_courant.append_text(ligne)
404                 else :
405                     # il s'agit d'un nouveau commentaire entre deux commandes
406                     # --> on le crée et il devient le commentaire courant
407                     commentaire_courant = COMMENTAIRE(self)
408                     commentaire_courant.append_text(ligne)
409
410                 #on passe à la ligne suivante
411                 continue
412
413             # la ligne contient des données autre qu'un éventuel commentaire
414             if commentaire_courant :
415                 # on clôt un éventuel commentaire courant
416                 commentaire_courant = None
417
418             if commande_commentarisee_courante :
419                 # on clôt une éventuelle commande commentarisee courante
420                 commande_commentarisee_courante = None
421
422             if commande_courante :
423                 #on a une commande en cours. On l'enrichit ou on la termine
424                 commande_courante.append_text(ligne)
425                 if not linecontinueRE.search(line) \
426                    and (hangingBraces == emptyHangingBraces) \
427                    and not hangingComments:
428                     #la commande est terminée 
429                     #print "fin de commande"
430                     self.analyse_reel(commande_courante.texte)
431                     commande_courante = None
432
433                 #on passe à la ligne suivante
434                 continue
435
436             if affectation_courante != None :
437                 #poursuite d'une affectation
438                 affectation_courante.append_text(ligne)
439                 if not linecontinueRE.search(line) \
440                    and (hangingBraces == emptyHangingBraces) \
441                    and not hangingComments:
442                     #L'affectation est terminée
443                     affectation_courante=None
444                 #on passe à la ligne suivante
445                 continue
446
447             # il peut s'agir d'une commande ou d'une affectation ...
448             # ou d'un EVAL !!!
449             if self.is_eval(ligne):
450                 # --> affectation de type EVAL
451                 if affectation_courante : affectation_courante = None
452                 affectation = AFFECTATION_EVAL(self)
453                 affectation.append_text(ligne)
454                 #on passe à la ligne suivante
455                 continue
456
457             if self.is_affectation(ligne):
458                 # --> affectation
459                 text=ligne
460                 #traitement des commentaires en fin de ligne
461                 compos=line.find("#")
462                 if compos > 2:
463                     #commentaire en fin de ligne
464                     #on cree un nouveau commentaire avant le parametre
465                     COMMENTAIRE(self).append_text(ligne[compos:])
466                     text=ligne[:compos]
467                 #si plusieurs instructions separees par des ; sur la meme ligne
468                 inspos=line.find(";")
469                 if inspos > 2:
470                     #on garde seulement la premiere partie de la ligne
471                     #si on a que des blancs apres le point virgule
472                     if string.strip(text[inspos:]) == ";":
473                         text=text[:inspos]
474                     else:
475                         raise FatalError("Eficas ne peut pas traiter plusieurs instructions sur la meme ligne : %s" % ligne)
476
477                 affectation_courante = AFFECTATION(self)
478                 affectation_courante.append_text(text)
479                 if not linecontinueRE.search(line) \
480                    and (hangingBraces == emptyHangingBraces) \
481                    and not hangingComments:
482                     #L'affectation est terminée
483                     affectation_courante=None
484                 #on passe à la ligne suivante
485                 continue
486
487             if self.is_commande(ligne):
488                 # --> nouvelle commande
489                 affectation_courante = None
490                 commande_courante = COMMANDE(self)
491                 commande_courante.append_text(ligne)
492                 #si la commande est complète, on la termine
493                 if not linecontinueRE.search(line) \
494                    and (hangingBraces == emptyHangingBraces) \
495                    and not hangingComments:
496                     #la commande est terminée 
497                     #print "fin de commande"
498                     self.analyse_reel(commande_courante.texte)
499                     commande_courante = None
500                 #on passe à la ligne suivante
501                 continue
502
503     def enleve (self,texte) :
504         """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations
505            Le nouveau texte est retourné
506         """
507         i=0
508         chaine=""
509         while (i<len(texte)):
510           if (texte[i] == " " or texte[i] == "\n" or texte[i] == "\t") :
511              i=i+1
512           else :
513              chaine=chaine+texte[i]
514              i=i+1
515         return chaine 
516             
517     def construit_genea(self,texte):
518         indiceC=0
519         mot=""
520         dict_reel_concept={}
521
522         # traitement pour chaque caractere
523         while (indiceC < len(texte)): 
524            c=texte[indiceC]
525            if ( c == "," or c == "(" or c == ")"):
526               mot=""
527            elif ( c== "="):
528               #on doit trouver derriere soit une valeur soit une parenthese
529               valeur=""
530               nouvelindice=indiceC+1
531               if texte[nouvelindice] != "(":
532                  #pas de parenthese ouvrante derriere un signe =, on a une valeur.
533                  while ( texte[nouvelindice] != "," and texte[nouvelindice] != ")"):
534                     valeur=valeur+texte[nouvelindice]
535                     nouvelindice=nouvelindice+1
536                     if nouvelindice == len(texte) :
537                         nouvelindice=nouvelindice -1
538                         break
539                  if mot in self.appli.liste_simp_reel:
540                     if valeur[0] != "'":
541                        try :
542                          clef=eval(valeur)
543                          if str(clef) != str(valeur) :
544                             dict_reel_concept[clef]=valeur
545                        except :
546                          pass
547                  mot=""
548                  indiceC=nouvelindice
549               else:
550                  #parenthese ouvrante derriere un signe =, on a un tuple de valeur ou de mots cles facteurs.
551                  # s agit -il d un tuple 
552                  if texte[nouvelindice+1] != "(":
553                     #le suivant n'est pas une parenthese ouvrante : on a un tuple de valeurs ou un mot cle facteur
554                     tuple=False
555                     #on avance jusqu'a la fin du tuple de valeurs ou jusqu'a la fin du premier mot cle simple
556                     #contenu dans le mot cle facteur
557                     while ( texte[nouvelindice] != "="):
558                        if texte[nouvelindice] == ")" :
559                           tuple=True
560                           break
561                        else :
562                           nouvelindice=nouvelindice+1
563                           if nouvelindice == len(texte) :
564                              nouvelindice=nouvelindice -1
565                              break
566                     if tuple :
567                        #cas du tuple de valeurs
568                        valeur=texte[indiceC+1:nouvelindice+1]
569                        indiceC=nouvelindice+1 
570                        if mot in self.appli.liste_simp_reel:
571                           valeur=valeur[1:-1]
572                           for val in valeur.split(',') :
573                           # Attention la derniere valeur est""
574                              try :
575                                 if val[0] != "'":
576                                   clef=eval(val)
577                                   if str(clef) != str(val) :
578                                      dict_reel_concept[clef]=val
579                              except :
580                                   pass
581                        mot=""
582                # ou de ( imbriqueés
583                  else :
584                     #cas du mocle facteur simple ou 
585                     mot=""
586            else :
587               mot=mot+texte[indiceC]
588            indiceC=indiceC+1
589         # traitement du dernier inutile
590         # c est un ; 
591         return dict_reel_concept
592
593     def analyse_reel(self,commande) :
594         nomConcept=None
595         # On verifie qu on a bien un OPER
596         # et pas une MACRO
597         if commande.find("=") > commande.find("(") :
598            return
599         if commande.find("=") > 0:
600            #epure1=self.enleve(commande)
601            epure1=pattern_blancs.sub("",commande)
602            nomConcept,corps=epure1.split("=",1)
603            epure2=corps.replace("_F(","(")
604            #nomConcept=epure1.split("=")[0]
605            #index=epure1.find("=")
606            #epure2=epure1[index+1:len(epure1)].replace("_F(","(")
607            #dict_reel_concept=self.construit_genea(epure2)
608            dict_reel_concept=construit_genea(epure2,self.appli.liste_simp_reel)
609         if nomConcept !=None :
610            if len(dict_reel_concept) != 0:
611               self.appli.dict_reels[nomConcept]=dict_reel_concept
612
613     def get_texte(self,appli=None):
614         """
615         Retourne le texte issu de l'analyse
616         """
617         self.appli=appli
618         try:
619             if not self.l_objets : self.analyse()
620             txt=''
621             for obj in self.l_objets:
622                 txt = txt+str(obj)
623         except ParserException:
624             #Impossible de convertir le texte, on le retourne tel que
625             txt=self.texte
626         return txt
627
628 def test():
629   import parseur_python
630   import doctest
631   doctest.testmod(parseur_python)
632
633
634 if __name__ == "__main__" :
635     import time
636     #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
637     fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
638     fichier = '/local/chris/ASTER/Eficas/Eficas1_10/EficasV1/Tests/testcomm/b.comm'
639     fichier = '/local/chris/ASTER/instals/STA8.2/astest/forma12c.comm'
640     fichier = 'titi.comm'
641     fichier = '../Aster/sdls300a.comm'
642     texte = open(fichier,'r').read()
643     class appli:
644        dict_reels={}
645        liste_simp_reel=["VALE","VALE_C","GROUP_MA","RAYON"]
646     a=appli()
647
648     if 1:
649         t0=time.clock()
650         txt = PARSEUR_PYTHON(texte).get_texte(a)
651         print t0,time.clock()-t0
652     else:
653         import hotshot, hotshot.stats
654         prof = hotshot.Profile("stones.prof")
655         txt = prof.runcall(PARSEUR_PYTHON(texte).get_texte,a)
656         prof.close()
657         stats = hotshot.stats.load("stones.prof")
658         stats.strip_dirs()
659         stats.sort_stats('time', 'calls')
660         stats.print_stats(20)
661
662     print txt
663     compile(txt, '<string>', 'exec')
664     print a.dict_reels