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