Salome HOME
sauve du 20/12
[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 is_modification_catalogue(self,texte) :
343         if self.pattern_commande.match(texte):
344            return 1
345
346     def analyse(self):
347         """
348         Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
349         et de commentaires (parmi lesquels des instructions "commentarisées").
350         """
351         l_lignes = string.split(self.texte,'\n')
352         commentaire_courant             = None
353         commande_courante               = None
354         affectation_courante            = None
355         commande_commentarisee_courante = None
356         self.l_objets = []
357
358         #initialisation du nombre de parentheses non fermees et de commentaires non termines
359         #Attention a reinitialiser en fin de ligne logique
360         #Une ligne logique peut s'etendre sur plusieurs lignes physiques avec des caracteres de continuation
361         #explicites ou implicites
362         hangingBraces = list(emptyHangingBraces)
363         hangingComments = 0
364
365         #Masquage des commentaires et strings multilignes
366         srcMasked=maskStringsAndComments('\n'.join(l_lignes))
367         #print srcMasked
368         masked_lines=srcMasked.split('\n')
369         lineno=0
370
371         for ligne in l_lignes :
372             line=masked_lines[lineno]
373             lineno=lineno+1
374             #print "ligne:",line
375             # mise a jour du nombre total de parentheses ouvertes (non fermees)
376             # et du nombre de commentaires non termines
377             for i in range(len(implicitContinuationChars)):
378                 contchar = implicitContinuationChars[i]
379                 numHanging = hangingBraces[i]
380                 hangingBraces[i] = numHanging+line.count(contchar[0]) - line.count(contchar[1])
381
382             hangingComments ^= line.count('"""') % 2
383             hangingComments ^= line.count(u"'''") % 2
384             #print hangingComments,hangingBraces
385             if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0: 
386                 raise ParserException()
387
388             if string.strip(ligne) == '':
389                 # il s'agit d'un saut de ligne
390                 # --> on l'ignore
391                 continue
392
393             if pattern_2comments.match(ligne):
394                 #on a trouvé une commande commentarisée : double commentaire sans rien devant a part des blancs
395                 if commentaire_courant:
396                     #Si un commentaire ordinaire est en cours on le termine
397                     commentaire_courant = None
398
399                 if commande_courante :
400                     # on a un objet commentarisé a l'intérieur d'une commande
401                     # --> non traité pour l'instant : on l'ajoute simplement a la commande courante comme
402                     # un commentaire ordinaire
403                     commande_courante.append_text(ligne)
404                 elif commande_commentarisee_courante :
405                     # commande_commentarisee en cours : on ajoute la ligne
406                     commande_commentarisee_courante.append_text(ligne)
407                     # on a 2 commandes commentarisées de suite
408                     if pattern_finComments.match(ligne) :
409                        commande_commentarisee_courante = None
410                 else:
411                     # debut de commande commentarisée : on crée un objet commande_commentarisee_courante
412                     commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
413                     commande_commentarisee_courante.append_text(ligne)
414
415                 #on passe a la ligne suivante
416                 continue
417
418             if pattern_comment.match(ligne):
419                 #commentaire ordinaire avec seulement des blancs devant
420                 if commande_commentarisee_courante :
421                     # commande_commentarisee en cours : on la clot
422                     commande_commentarisee_courante = None
423
424                 if commande_courante :
425                     # il s'agit d'un commentaire a l'intérieur d'une commande --> on ne fait rien de special
426                     #on l'ajoute au texte de la commande 
427                     commande_courante.append_text(ligne)
428                 elif commentaire_courant :
429                     # il s'agit de la nième ligne d'un commentaire entre deux commandes
430                     # --> on ajoute cette ligne au commentaire courant
431                     commentaire_courant.append_text(ligne)
432                 else :
433                     # il s'agit d'un nouveau commentaire entre deux commandes
434                     # --> on le crée et il devient le commentaire courant
435                     commentaire_courant = COMMENTAIRE(self)
436                     commentaire_courant.append_text(ligne)
437
438                 #on passe a la ligne suivante
439                 continue
440
441             # la ligne contient des données autre qu'un éventuel commentaire
442             if commentaire_courant :
443                 # on clot un éventuel commentaire courant
444                 commentaire_courant = None
445
446             if commande_commentarisee_courante :
447                 # on clot une éventuelle commande commentarisee courante
448                 commande_commentarisee_courante = None
449
450             if commande_courante :
451                 #on a une commande en cours. On l'enrichit ou on la termine
452                 commande_courante.append_text(ligne)
453                 if not linecontinueRE.search(line) \
454                    and (hangingBraces == emptyHangingBraces) \
455                    and not hangingComments:
456                     #la commande est terminée 
457                     #print "fin de commande"
458                     self.analyse_reel(commande_courante.texte)
459                     commande_courante = None
460
461                 #on passe a la ligne suivante
462                 continue
463
464             if affectation_courante != None :
465                 #poursuite d'une affectation
466                 affectation_courante.append_text(ligne)
467                 if not linecontinueRE.search(line) \
468                    and (hangingBraces == emptyHangingBraces) \
469                    and not hangingComments:
470                     #L'affectation est terminée
471                     affectation_courante=None
472                 #on passe a la ligne suivante
473                 continue
474
475             # il peut s'agir d'une commande ou d'une affectation ...
476             # ou d'un EVAL !!!
477             if self.is_eval(ligne):
478                 # --> affectation de type EVAL
479                 if affectation_courante : affectation_courante = None
480                 affectation = AFFECTATION_EVAL(self)
481                 affectation.append_text(ligne)
482                 #on passe a la ligne suivante
483                 continue
484
485             if self.is_affectation(ligne):
486                 # --> affectation
487                 text=ligne
488                 #traitement des commentaires en fin de ligne
489                 compos=line.find(u"#")
490                 if compos > 2:
491                     #commentaire en fin de ligne
492                     #on cree un nouveau commentaire avant le parametre
493                     COMMENTAIRE(self).append_text(ligne[compos:])
494                     text=ligne[:compos]
495                 #si plusieurs instructions separees par des ; sur la meme ligne
496                 inspos=line.find(u";")
497                 if inspos > 2:
498                     #on garde seulement la premiere partie de la ligne
499                     #si on a que des blancs apres le point virgule
500                     if string.strip(text[inspos:]) == ";":
501                         text=text[:inspos]
502                     else:
503                         raise FatalError(tr("Eficas ne peut pas traiter plusieurs instructions \
504                                                  sur la meme ligne : %s", ligne))
505
506                 affectation_courante = AFFECTATION(self)
507                 affectation_courante.append_text(text)
508                 if not linecontinueRE.search(line) \
509                    and (hangingBraces == emptyHangingBraces) \
510                    and not hangingComments:
511                     #L'affectation est terminée
512                     affectation_courante=None
513                 #on passe a la ligne suivante
514                 continue
515
516             if self.is_commande(ligne):
517                 # --> nouvelle commande
518                 affectation_courante = None
519                 commande_courante = COMMANDE(self)
520                 commande_courante.append_text(ligne)
521                 #si la commande est complète, on la termine
522                 if not linecontinueRE.search(line) \
523                    and (hangingBraces == emptyHangingBraces) \
524                    and not hangingComments:
525                     #la commande est terminée 
526                     #print "fin de commande"
527                     self.analyse_reel(commande_courante.texte)
528                     commande_courante = None
529                 #on passe a la ligne suivante
530                 continue
531
532             #if self.is_modification_catalogue(ligne) :
533             #   print ligne
534  
535     def enleve (self,texte) :
536         """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations
537            Le nouveau texte est retourné
538         """
539         i=0
540         chaine=""
541         while (i<len(texte)):
542           if (texte[i] == " " or texte[i] == "\n" or texte[i] == "\t") :
543              i=i+1
544           else :
545              chaine=chaine+texte[i]
546              i=i+1
547         return chaine 
548             
549     def construit_genea(self,texte):
550         indiceC=0
551         mot=""
552         dict_reel_concept={}
553
554         # traitement pour chaque caractere
555         while (indiceC < len(texte)): 
556            c=texte[indiceC]
557            if ( c == "," or c == "(u" or c == ")"):
558               mot=""
559            elif ( c== "="):
560               #on doit trouver derriere soit une valeur soit une parenthese
561               valeur=""
562               nouvelindice=indiceC+1
563               if texte[nouvelindice] != "(u":
564                  #pas de parenthese ouvrante derriere un signe =, on a une valeur.
565                  while ( texte[nouvelindice] != "," and texte[nouvelindice] != ")"):
566                     valeur=valeur+texte[nouvelindice]
567                     nouvelindice=nouvelindice+1
568                     if nouvelindice == len(texte) :
569                         nouvelindice=nouvelindice -1
570                         break
571                  if mot in self.appli.liste_simp_reel:
572                     if valeur[0] != "'":
573                        try :
574                          clef=eval(valeur)
575                          if str(clef) != str(valeur) :
576                             dict_reel_concept[clef]=valeur
577                        except :
578                          pass
579                  mot=""
580                  indiceC=nouvelindice
581               else:
582                  #parenthese ouvrante derriere un signe =, on a un tuple de valeur ou de mots cles facteurs.
583                  # s agit -il d un tuple 
584                  if texte[nouvelindice+1] != "(u":
585                     #le suivant n'est pas une parenthese ouvrante : on a un tuple de valeurs ou un mot cle facteur
586                     tuple=False
587                     #on avance jusqu'a la fin du tuple de valeurs ou jusqu'a la fin du premier mot cle simple
588                     #contenu dans le mot cle facteur
589                     while ( texte[nouvelindice] != "="):
590                        if texte[nouvelindice] == ")" :
591                           tuple=True
592                           break
593                        else :
594                           nouvelindice=nouvelindice+1
595                           if nouvelindice == len(texte) :
596                              nouvelindice=nouvelindice -1
597                              break
598                     if tuple :
599                        #cas du tuple de valeurs
600                        valeur=texte[indiceC+1:nouvelindice+1]
601                        indiceC=nouvelindice+1 
602                        if mot in self.appli.liste_simp_reel:
603                           valeur=valeur[1:-1]
604                           for val in valeur.split(',') :
605                           # Attention la derniere valeur est""
606                              try :
607                                 if val[0] != "'":
608                                   clef=eval(val)
609                                   if str(clef) != str(val) :
610                                      dict_reel_concept[clef]=val
611                              except :
612                                   pass
613                        mot=""
614                # ou de ( imbriqueés
615                  else :
616                     #cas du mocle facteur simple ou 
617                     mot=""
618            else :
619               mot=mot+texte[indiceC]
620            indiceC=indiceC+1
621         # traitement du dernier inutile
622         # c est un ; 
623         return dict_reel_concept
624
625     def analyse_reel(self,commande) :
626         nomConcept=None
627         # On verifie qu on a bien un OPER
628         # et pas une MACRO
629         if commande.find(u"=") > commande.find(u"(u") :
630            return
631         if commande.find(u"=") > 0:
632            #epure1=self.enleve(commande)
633            epure1=pattern_blancs.sub(u"",commande)
634            nomConcept,corps=epure1.split(u"=",1)
635            epure2=corps.replace(u"_F(u","(u")
636            #nomConcept=epure1.split(u"=")[0]
637            #index=epure1.find(u"=")
638            #epure2=epure1[index+1:len(epure1)].replace(u"_F(u","(u")
639            #dict_reel_concept=self.construit_genea(epure2)
640            if self.appli:
641              dict_reel_concept=construit_genea(epure2,self.appli.liste_simp_reel)
642            else:
643              dict_reel_concept={}
644         if nomConcept == "sansnom" :
645            nomConcept = ""
646         if nomConcept !=None :
647            if len(dict_reel_concept) != 0:
648               self.appli.dict_reels[nomConcept]=dict_reel_concept
649
650     def get_texte(self,appli=None):
651         """
652         Retourne le texte issu de l'analyse
653         """
654         self.appli=appli
655         try:
656         #if 1:
657             if not self.l_objets : self.analyse()
658             txt=''
659             for obj in self.l_objets:
660                 txt = txt+str(obj)
661         #else :
662         except  ParserException:
663             #Impossible de convertir le texte, on le retourne tel que
664             txt=self.texte
665         return txt
666
667 def test():
668   import parseur_python
669   import doctest
670   doctest.testmod(parseur_python)
671
672
673 if __name__ == "__main__" :
674     import time
675     #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
676     fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
677     fichier = '/local/chris/ASTER/Eficas/Eficas1_10/EficasV1/Tests/testcomm/b.comm'
678     fichier = '/local/chris/ASTER/instals/STA8.2/astest/forma12c.comm'
679     fichier = 'titi.comm'
680     fichier = '../Aster/sdls300a.comm'
681     fichier = '../Aster/az.comm'
682     texte = open(fichier,'r').read()
683     class appli:
684        dict_reels={}
685        liste_simp_reel=["VALE","VALE_C","GROUP_MA","RAYON"]
686     a=appli()
687
688     if 1:
689         t0=time.clock()
690         txt = PARSEUR_PYTHON(texte).get_texte(a)
691         print t0,time.clock()-t0
692     else:
693         import hotshot, hotshot.stats
694         prof = hotshot.Profile(u"stones.prof")
695         txt = prof.runcall(PARSEUR_PYTHON(texte).get_texte,a)
696         prof.close()
697         stats = hotshot.stats.load(u"stones.prof")
698         stats.strip_dirs()
699         stats.sort_stats('time', 'calls')
700         stats.print_stats(20)
701
702     print txt
703     compile(txt, '<string>', 'exec')
704     print a.dict_reels