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