Salome HOME
excep et print
[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
40 def maskStringsAndComments(src):
41     """Masque tous les caracteres de src contenus dans des commentaires ou des strings multilignes (triples
42        quotes et guillemets.
43        Le masquage est realise en remplacant les caracteres par des * 
44        Attention : cette fonction doit etre utilisee sur un texte complet et pas ligne par ligne
45     """
46 # remplace les \\, les \" les \'  par **
47 # supprime toutes les chaines ou commentaires ,y compris multiligne i
48 # entre 3 ou 1 simples ou doubles quotes (ouvrantes fermantes) ou # 
49 # laisse les non fermantes ou non ouvrantes
50     #src = escapedQuotesRE.sub(u"**", src)
51     # le u met le bazar dans le translate
52     src = escapedQuotesRE.sub("**", src)
53     allstrings = stringsAndCommentsRE.split(src)
54     # every odd element is a string or comment
55     for i in xrange(1, len(allstrings), 2):
56         if allstrings[i].startswith(u"'''")or allstrings[i].startswith('"""'):
57             allstrings[i] = allstrings[i][:3]+ \
58                             allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
59                             allstrings[i][-3:]
60         else:
61             allstrings[i] = allstrings[i][0]+ \
62                             allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
63                             allstrings[i][-1]
64
65     return "".join(allstrings)
66
67 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
68 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
69 emptyHangingBraces = [0,0,0,0,0]
70
71 class ParserException(Exception): pass
72 class FatalError(Exception): pass
73
74 #commentaire double precede d'un nombre quelconque de blancs (pas multiligne)
75 pattern_2comments   = re.compile(r"^\s*##.*")
76 pattern_finComments = re.compile("^\s*##Fin Commentaire")
77 #commentaire standard precede d'un nombre quelconque de blancs (pas multiligne)
78 pattern_comment   = re.compile(r"^\s*#.*")
79 #fin de ligne ; suivi d'un nombre quelconque de blancs (pas multiligne)
80 pattern_fin   = re.compile(r"; *$")
81 #pattern pour supprimer les blancs, tabulations et fins de ligne
82 pattern_blancs = re.compile(r"[ \t\r\f\v]")
83 #pattern_blancs = re.compile(r"[\s\n]")
84 number_kw_pattern=re.compile(r"""
85 (
86     #groupe nombre decimal
87     (?:
88         #signe : on ignore le signe +
89         [-]?
90         #groupe (avec ?: n'apparait pas en tant que groupe dans le resultat)
91         (?:
92             #mantisse forme entiere.fractionnaire
93             \d+(?:\.\d*)?
94             |
95             #ou forme .fractionnaire
96             \.\d+
97         )
98         (?:[eE][+-]?\d+)?
99     )
100     |
101     #argument keyword
102     [a-zA-Z_]\w*=
103 )
104 """,re.VERBOSE|re.MULTILINE)
105
106 def construit_genea(texte,liste_mc):
107     """
108        Retourne un dictionnaire dont les cles sont des reels et les valeurs sont leurs representations textuelles.
109
110        Realise un filtrage sur les reels :
111
112          - Ne garde que les reels pour lesquels str ne donne pas une bonne representation.
113          - Ne garde que les reels derriere un argument keyword dont le nom est dans liste_mc
114
115        >>> 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),
116        ... #POMPE_PRIMA._BOUCLE_N._2_ELEMENT_NUMERO:0239
117        ... h=_F(x=34.6,y=-1)'''
118        >>> construit_genea(s,['a','x'])
119        {0.000213: '21.3e-5'}
120     """
121     d={}
122     mot=""
123     #on masque les strings et commentaires pour ne pas identifier de faux reels
124     for m in number_kw_pattern.findall(maskStringsAndComments(texte)):
125         if m[-1] == '=':
126             #argument keyword
127             mot=m[:-1]
128         else:
129             if mot not in liste_mc:continue
130             #valeur
131             key=eval(m)
132             if str(key) != m: d[key]=m
133     return d
134
135
136 class ENTITE_JDC :
137     """Classe de base pour tous les objets créés lors de la conversion
138        Tout objet dérivé est enregistré aupres de son pere a sa création
139     """
140     def __init__(self,pere):
141         self.texte = ''
142         pere.l_objets.append(self)
143
144     def set_text(self,texte):
145         self.texte = texte
146
147     def append_text(self,texte):
148         """
149         Ajoute texte a self.texte en mettant un retour chariot a la fin de texte
150         """
151         texte = texte+'\n'
152         self.texte = self.texte +texte
153
154     def __str__(self):
155         return self.texte
156
157 class COMMENTAIRE(ENTITE_JDC):
158
159     def __str__(self):
160         """
161         Retourne une chaine de caracteres représentants self
162         sous une forme interprétable par EFICAS
163         """
164         t=repr(self.texte)
165         return "COMMENTAIRE(u"+t+")\n"
166
167         #s='COMMENTAIRE(u"""'+self.texte+'""")\n\n'
168         #return s
169
170     def append_text(self,texte):
171         """
172         Ajoute texte a self.texte en enlevant le # initial
173         """
174         texte = texte+'\n'
175         if texte[0] == '#':
176             self.texte = self.texte+texte[1:]
177         else:
178             # le diese n'est pas sur le premier caractere
179             amont,aval = string.split(texte,'#',1) # on découpe suivant la premiere occurrence de #
180             self.texte = self.texte +amont + aval
181         
182 class COMMANDE(ENTITE_JDC):
183
184     def __str__(self):
185         """
186         Retourne self.texte
187         """
188         return self.texte+'\n'
189         
190     def get_nb_par(self):
191         """
192         Retourne la différence entre le nombre de parentheses ouvrantes
193         et le nombre de parentheses fermantes présentes dans self.texte
194         Peut donc retourner un entier négatif
195         """
196         # faire attention aux commentaires contenus dans self.texte
197         # qui peuvent eux-memes contenir des parentheses !!!!
198         l_lignes = string.split(self.texte,'\n')
199         nb = 0
200         for ligne in l_lignes:
201             ligne = string.split(ligne,'#')[0]
202             nb = nb + (string.count(ligne,'(')-string.count(ligne,')'))
203         return nb
204
205 class AFFECTATION(ENTITE_JDC):
206
207     def append_text(self,texte):
208         """
209         Ajoute texte a self.texte en enlevant tout retour chariot et tout point virgule
210         PN et tout commentaire
211         """
212         if texte[-1] == '\n' : texte = string.rstrip(texte[0:-1])
213         if texte[-1] == ';' : texte = string.rstrip(texte[0:-1])
214         self.texte = self.texte+texte+'\n'
215         
216     def __str__(self):
217         """
218         Retourne une expression de l'affectation compréhensible par ACCAS
219         et exploitable par EFICAS
220         """
221         nom,valeur = string.split(self.texte,'=',1)
222         n = string.rstrip(nom)
223         nom = string.lstrip(n)
224         if valeur[-1] == '\n': valeur = valeur[:-1]
225         return n + ' = PARAMETRE(nom=\''+nom+'\',valeur='+valeur+')\n'
226
227 class COMMANDE_COMMENTARISEE(ENTITE_JDC):
228
229     def append_text(self,texte):
230         """
231         Ajoute texte a self.texte en enlevant les doubles commentaires
232         """
233         texte = string.strip(texte)
234         texte = string.strip(texte[2:])
235         self.texte = self.texte+(len(self.texte)>0)*'\n'+texte
236
237     def __str__(self):
238         """
239         Retourne une expression de la commande commentarisée compréhensible par ACCAS
240         et exploitable par EFICAS
241         """
242         return "COMMANDE_COMM(texte="+repr(self.texte)+")\n"
243         #return "COMMANDE_COMM(texte='''"+self.texte+"''')\n"
244
245 class AFFECTATION_EVAL(ENTITE_JDC):
246
247     def append_text(self,texte):
248         """
249         Ajoute texte a self.texte en enlevant tout retour chariot
250         """
251         if texte[-1] == '\n' : texte = texte[1:-1]
252         self.texte = self.texte+texte
253         
254     def __str__(self):
255         """
256         Retourne une expression du parametre EVAL compréhensible par ACCAS
257         et exploitable par EFICAS
258         """
259         nom,valeur = string.split(self.texte,'=',1)
260         nom = string.strip(nom)
261         if valeur[-1] == '\n': valeur = valeur[:-1]
262         valeur = string.strip(valeur)
263         return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n'
264         
265 class PARSEUR_PYTHON:
266     """
267     Cette classe sert a générer un objet PARSEUR_PYTHON qui réalise l'analyse d'un texte 
268     représentant un JDC Python en distinguant :
269       - les commentaires inter commandes
270       - les affectations
271       - les commandes
272     """
273     pattern_commande   = re.compile(r'^([A-Z][A-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)')
274     pattern_eval       = re.compile(r'^(EVAL)([ \t\r\f\v]*)\(([\w\W]*)')
275     pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+')
276     pattern_name       = re.compile(r'[a-zA-Z_]\w*')
277     
278     def __init__(self,texte):
279         self.texte = texte
280         self.l_objets=None
281         self.appli=None
282
283     def is_affectation(self,texte):
284         """
285         Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes
286         Aster, 0 sinon
287         """
288         if '=' not in texte : return 0
289         if self.pattern_commande.match(texte):
290             # cas d'une procédure ...
291             return 0
292         amont,aval = string.split(texte,'=',1)
293         aval = string.strip(aval)
294         if self.pattern_commande.match(aval):
295             return 0
296         else:
297             s= string.strip(amont)
298             m= self.pattern_name.match(s)
299             if m is None : return 0
300             if m.start() != 0 :return 0
301             if m.end() != len(s):return 0
302             return 1
303
304     def is_eval(self,texte):
305         """
306         Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL
307         dans un jeu de commandes Aster, 0 sinon
308         """
309         if '=' not in texte : return 0
310         if self.pattern_commande.match(texte):
311             # cas d'une procédure ...
312             return 0
313         amont,aval = string.split(texte,'=',1)
314         aval = string.strip(aval)
315         if not self.pattern_commande.match(aval) : return 0
316         if self.pattern_eval.match(aval):
317             return 1
318         else:
319             return 0
320             
321     def is_commande(self,texte):
322         """
323         Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes
324         Aster, 0 sinon
325         """
326         if self.pattern_commande.match(texte):
327             # cas d'une procédure ...
328             return 1
329         # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' !
330         if '=' not in texte : return 0
331         # on a un texte de la forme xxxx = yyyyy
332         # --> reste a analyser yyyy
333         amont,aval = string.split(texte,'=',1)
334         aval = string.strip(aval)
335         if self.pattern_commande.match(aval):
336             return 1
337         else:
338             return 0
339
340     def is_modification_catalogue(self,texte) :
341         if self.pattern_commande.match(texte):
342            return 1
343
344     def analyse(self):
345         """
346         Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
347         et de commentaires (parmi lesquels des instructions "commentarisées").
348         """
349         l_lignes = string.split(self.texte,'\n')
350         commentaire_courant             = None
351         commande_courante               = None
352         affectation_courante            = None
353         commande_commentarisee_courante = None
354         self.l_objets = []
355
356         #initialisation du nombre de parentheses non fermees et de commentaires non termines
357         #Attention a reinitialiser en fin de ligne logique
358         #Une ligne logique peut s'etendre sur plusieurs lignes physiques avec des caracteres de continuation
359         #explicites ou implicites
360         hangingBraces = list(emptyHangingBraces)
361         hangingComments = 0
362
363         #Masquage des commentaires et strings multilignes
364         srcMasked=maskStringsAndComments('\n'.join(l_lignes))
365         masked_lines=srcMasked.split('\n')
366         lineno=0
367
368         for ligne in l_lignes :
369             line=masked_lines[lineno]
370             lineno=lineno+1
371             #print ("ligne:",line)
372             # mise a jour du nombre total de parentheses ouvertes (non fermees)
373             # et du nombre de commentaires non termines
374             for i in range(len(implicitContinuationChars)):
375                 contchar = implicitContinuationChars[i]
376                 numHanging = hangingBraces[i]
377                 hangingBraces[i] = numHanging+line.count(contchar[0]) - line.count(contchar[1])
378
379             hangingComments ^= line.count('"""') % 2
380             hangingComments ^= line.count(u"'''") % 2
381             #print (hangingComments,hangingBraces)
382             if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0: 
383                 raise ParserException()
384
385             if string.strip(ligne) == '':
386                 # il s'agit d'un saut de ligne
387                 # --> on l'ignore
388                 continue
389
390             if pattern_2comments.match(ligne):
391                 #on a trouvé une commande commentarisée : double commentaire sans rien devant a part des blancs
392                 if commentaire_courant:
393                     #Si un commentaire ordinaire est en cours on le termine
394                     commentaire_courant = None
395
396                 if commande_courante :
397                     # on a un objet commentarisé a l'intérieur d'une commande
398                     # --> non traité pour l'instant : on l'ajoute simplement a la commande courante comme
399                     # un commentaire ordinaire
400                     commande_courante.append_text(ligne)
401                 elif commande_commentarisee_courante :
402                     # commande_commentarisee en cours : on ajoute la ligne
403                     commande_commentarisee_courante.append_text(ligne)
404                     # on a 2 commandes commentarisées de suite
405                     if pattern_finComments.match(ligne) :
406                        commande_commentarisee_courante = None
407                 else:
408                     # debut de commande commentarisée : on crée un objet commande_commentarisee_courante
409                     commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
410                     commande_commentarisee_courante.append_text(ligne)
411
412                 #on passe a la ligne suivante
413                 continue
414
415             if pattern_comment.match(ligne):
416                 #commentaire ordinaire avec seulement des blancs devant
417                 if commande_commentarisee_courante :
418                     # commande_commentarisee en cours : on la clot
419                     commande_commentarisee_courante = None
420
421                 if commande_courante :
422                     # il s'agit d'un commentaire a l'intérieur d'une commande --> on ne fait rien de special
423                     #on l'ajoute au texte de la commande 
424                     commande_courante.append_text(ligne)
425                 elif commentaire_courant :
426                     # il s'agit de la nieme ligne d'un commentaire entre deux commandes
427                     # --> on ajoute cette ligne au commentaire courant
428                     commentaire_courant.append_text(ligne)
429                 else :
430                     # il s'agit d'un nouveau commentaire entre deux commandes
431                     # --> on le crée et il devient le commentaire courant
432                     commentaire_courant = COMMENTAIRE(self)
433                     commentaire_courant.append_text(ligne)
434
435                 #on passe a la ligne suivante
436                 continue
437
438             # la ligne contient des données autre qu'un éventuel commentaire
439             if commentaire_courant :
440                 # on clot un éventuel commentaire courant
441                 commentaire_courant = None
442
443             if commande_commentarisee_courante :
444                 # on clot une éventuelle commande commentarisee courante
445                 commande_commentarisee_courante = None
446
447             if commande_courante :
448                 #on a une commande en cours. On l'enrichit ou on la termine
449                 commande_courante.append_text(ligne)
450                 if not linecontinueRE.search(line) \
451                    and (hangingBraces == emptyHangingBraces) \
452                    and not hangingComments:
453                     #la commande est terminée 
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 complete, on la termine
518                 if not linecontinueRE.search(line) \
519                    and (hangingBraces == emptyHangingBraces) \
520                    and not hangingComments:
521                     #la commande est terminee 
522                     self.analyse_reel(commande_courante.texte)
523                     commande_courante = None
524                 #on passe a la ligne suivante
525                 continue
526
527  
528     def enleve (self,texte) :
529         """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations
530            Le nouveau texte est retourne
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 ( imbriquees
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     compile(txt, '<string>', 'exec')
682     print (a.dict_reels)