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