Salome HOME
sauve0206
[tools/eficas.git] / convert / parseur_cas.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 import Accas
24
25 # mot cles a traiter : Discretisations_In_Space
26 from enumTelemac import dicoEnum
27
28 escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
29 stringsAndCommentsRE =  \
30       re.compile(u"(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
31 allchars = string.maketrans(u"", "")
32 allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
33 allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
34
35 ordreEtapes=('INITIALIZATION', 'TIDE_PARAMETERS', 'INITIAL_STATE', 'NUMERICAL_PARAMETERS', 'PHYSICAL_PARAMETERS',) 
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             allstrings[i] = allstrings[i][0]+ \
53                            allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
54                            allstrings[i][-1]
55
56     return "".join(allstrings)
57
58     
59 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
60 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
61 emptyHangingBraces = [0,0,0,0,0]
62
63 class ParserException(Exception): pass
64 class FatalError(Exception): pass
65
66 # ligne commençant par /
67 pattern_commentaireTelemac   = re.compile(r"^\s*/.*")
68 # ligne commençant par &
69 pattern_eperluetteTelemac   = re.compile(r"^&.*")
70 #commentaire double precede d'un nombre quelconque de blancs (pas multiligne)
71 pattern_2comments   = re.compile(r"^\s*##.*")
72 #commentaire standard precede d'un nombre quelconque de blancs (pas multiligne)
73 pattern_comment   = re.compile(r"^\s*#.*")
74 #fin de ligne ; suivi d'un nombre quelconque de blancs (pas multiligne)
75 pattern_fin   = re.compile(r"; *$")
76 #pattern pour supprimer les blancs, tabulations et fins de ligne
77 pattern_blancs = re.compile(r"[ \t\r\f\v]")
78 #pattern_blancs = re.compile(r"[\s\n]")
79 number_kw_pattern=re.compile(r"""
80 (
81     #groupe nombre decimal
82     (?:
83         #signe : on ignore le signe +
84         [-]?
85         #groupe (avec ?: n'apparait pas en tant que groupe dans le resultat)
86         (?:
87             #mantisse forme entiere.fractionnaire
88             \d+(?:\.\d*)?
89             |
90             #ou forme .fractionnaire
91             \.\d+
92         )
93         (?:[eE][+-]?\d+)?
94     )
95     |
96     #argument keyword
97     [a-zA-Z_]\w*=
98 )
99 """,re.VERBOSE|re.MULTILINE)
100
101 def construit_genea(texte,liste_mc):
102     """
103        Retourne un dictionnaire dont les cles sont des reels et les valeurs sont leurs representations textuelles.
104
105        Realise un filtrage sur les reels :
106
107          - Ne garde que les reels pour lesquels str ne donne pas une bonne representation.
108          - Ne garde que les reels derriere un argument keyword dont le nom est dans liste_mc
109
110        >>> 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),
111        ... #POMPE_PRIMA._BOUCLE_N._2_ELEMENT_NUMERO:0239
112        ... h=_F(x=34.6,y=-1)'''
113        >>> construit_genea(s,['a','x'])
114        {0.000213: '21.3e-5'}
115     """
116     d={}
117     mot=""
118     #on masque les strings et commentaires pour ne pas identifier de faux reels
119     for m in number_kw_pattern.findall(maskStringsAndComments(texte)):
120         if m[-1] == '=':
121             #argument keyword
122             mot=m[:-1]
123         else:
124             if mot not in liste_mc:continue
125             #valeur
126             key=eval(m)
127             if str(key) != m: d[key]=m
128     return d
129
130
131 ListeMCAExclure=("Computation_Continued",)
132 DicoMCAExclureSiValeur={"Computation_Continued" : "NO"}
133 ListeMCARecalculer=('tt',)
134 DicoMCARecalculerSiValeur={"Computation_Continued" : "YES"}
135 DicoMCAReformater = {"Variables_For_Graphic_Printouts": "texteEnListe", \
136                      "Solver" : "remplaceEnum" }
137 DicoPlusieursMC =  {"Type_Of_Advection": "decoupeAdvection" ,\
138                     }
139
140 class PARSEUR_CAS:
141   
142
143     pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+')
144     
145     def __init__(self,texte):
146         self.texte = texte
147         self.l_objets=None
148         self.appli=None
149
150     def get_texte(self,appli=None):
151         """
152         Retourne le texte issu de l'analyse
153         """
154         self.appli=appli
155         self.dicoInverse=self.appli.readercata.dicoInverse
156
157         try:
158             self.analyse()
159             txt=self.texteComm
160         except  ParserException:
161             #Impossible de convertir le texte, on le retourne tel que
162             txt=self.texte
163         return txt
164
165     def analyse(self):
166         """
167         Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
168         et de commentaires (parmi lesquels des instructions "commentarisées").
169         """
170         l_lignes = string.split(self.texte,'\n')
171         affectation_courante            = None
172         self.l_objets = []
173
174         #Masquage des commentaires et strings multilignes
175         #srcMasked=maskStringsAndComments('\n'.join(l_lignes))
176         #print srcMasked
177         #masked_lines=srcMasked.split('\n')
178
179         lineno=0
180         self.listeNomValeur=[]
181         for ligne in l_lignes :
182             #line=masked_lines[lineno]
183             lineno=lineno+1
184
185             if string.strip(ligne) == '': continue
186             if pattern_commentaireTelemac.match(ligne) : continue
187             if pattern_eperluetteTelemac.match(ligne)  : continue
188             # On remplace les : par un =
189             # On s assure que les = soient entoures d espace
190             # On remplace les espaces successifs par un seul
191             # On enleve les blancs en debut et fin de ligne
192             # On remplace les ' ; ' par des ;
193             ligne=ligne.replace(':','=')
194             ligne=ligne.replace('=',' = ')
195             ligne=re.sub(r';\s*',';',ligne)
196             ligne=re.sub(r'\s*;',';',ligne)
197             ligne=re.sub(r' \s*',' ',ligne)
198             ligne=re.sub(r'^\s','',ligne)
199             ligne=re.sub(r'\s$','',ligne)
200             listeMot=ligne.split(" ")
201             while listeMot != [] :
202                nom,listeMot    = self.construitNom(listeMot)
203                valeur,listeMot = self.construitValeur(listeMot)
204                bTraite, nom, valeur =self.verifieNom(nom,valeur)
205                if bTraite : self.listeNomValeur.append((nom, valeur))
206         self.construitTexteFinal()
207                
208                
209     def construitNom(self,liste):
210         nomEficas=''
211         index=0
212         for mot in liste :
213            index+=1
214            if mot in (":","=") : break
215            motE=mot[0].upper()+mot[1:].lower()
216            nomEficas+=motE+'_'
217         nouveauNom=nomEficas[0:-1].replace('-','_')
218         nouvelleListe=liste[index:]
219         return nouveauNom,nouvelleListe
220
221     def construitValeur(self,liste):
222         index=0
223         if liste[0][0]=="'" :
224            valeur=''
225            for mot in liste :
226                index+=1
227                valeur+=str(mot)+" "
228                if mot[-1]=="'":
229                   valeur=valeur[0:-1]
230                   break
231         elif liste[0].find(';') > -1 :
232           valeur=liste[0].split(';')
233           index=1
234         else : 
235           valeur=liste[0]
236           index=1
237         nouvelleListe=liste[index:]
238         return valeur,nouvelleListe
239                
240
241     def verifieNom(self,nom,valeur):
242         if nom in ListeMCAExclure : return (False, nom, valeur) 
243         if nom in DicoMCAExclureSiValeur.keys() :
244           if valeur != DicoMCAExclureSiValeur[nom] :  print "prevoir Traitement pour ", nom, valeur
245           return (False, nom, valeur)
246
247         bTrue=True
248         if nom in DicoMCAReformater.keys() :
249            bTrue,nom,valeur=apply(PARSEUR_CAS.__dict__[DicoMCAReformater[nom]],(self,nom,valeur))
250         if nom in DicoPlusieursMC.keys() :
251            bTrue,nom,valeur=apply(PARSEUR_CAS.__dict__[DicoPlusieursMC[nom]],(self,nom,valeur))
252            return (bTrue,nom,valeur)
253         if nom not in self.dicoInverse.keys() : 
254            print  "******** ", nom, " non encore connu ***********"
255            bTrue=False
256         return (bTrue, nom, valeur)
257
258     def remplaceEnum(self,nom,valeur):
259        newValeur=dicoEnum[nom][valeur]
260        return (True,nom,newValeur)
261        
262
263
264     def texteEnListe(self,nom,valeur): 
265        print "je passe dans decoupeEnListe pour ", nom,valeur
266        v1=re.sub(r'^\'','',valeur)
267        v2=re.sub(r'\'$','',v1)
268        newValeur=v2.split(',')
269        return (True,nom,newValeur)
270
271     def decoupeAdvection(self,nom,valeur):
272         # on met a jour la liste des valeurs ici : il y a plusieurs MC calcule
273         print "je passe dans decoupeAdvection pour",nom,valeur
274         self.listeNomValeur.append(('Advection_Of_U_And_V',True)) 
275         v=dicoEnum['Type_Of_Advection'][valeur[0]]
276         self.listeNomValeur.append(('Type_Of_Advection_U_And_V',v) )
277         if len(valeur)==1: return  (False,nom,valeur)
278
279         self.listeNomValeur.append(('Advection_Of_H',True)) 
280         v=dicoEnum['Type_Of_Advection'][valeur[1]]
281         self.listeNomValeur.append(('Type_Of_Advection_H',v)) 
282         if len(valeur)==2: return (False,nom,valeur)
283
284         self.listeNomValeur.append(('Advection_Of_Tracers',True)) 
285         v=dicoEnum['Type_Of_Advection'][valeur[2]]
286         self.listeNomValeur.append(('Type_Of_Advection_Tracers',v)) 
287         if len(valeur)==3: return (False,nom,valeur)
288
289         self.listeNomValeur.append(('Advection_Of_K_And_Epsilon',True)) 
290         v=dicoEnum['Type_Of_Advection'][valeur[3]]
291         self.listeNomValeur.append(('Type_Of_Advection_K_And_Epsilon',v)) 
292         # on retourne False, l append est deja fait
293         return (False,nom,valeur)
294
295     def construitTexteFinal(self):
296         self.dicoTexte={}
297         self.dicoNature={}
298         print self.listeNomValeur
299         for nomMC,valeur in self.listeNomValeur:
300             mc,objmc=self.dicoInverse[nomMC][0]
301             if nomMC=="Solver_Option" : print self.dicoInverse[nomMC][0]
302             self.dicoNature[mc]=objmc
303             liste=self.dicoInverse[nomMC][1:]
304             liste.reverse()
305             dico=self.dicoTexte
306             for (nom,obj) in liste:
307                if isinstance(obj,Accas.A_BLOC.BLOC) :
308                   continue
309                self.dicoNature[nom]=obj
310                if not(isinstance(obj,Accas.A_PROC.PROC)) and  not(isinstance(obj,Accas.A_FACT.FACT)) :
311                   print "******** ", nom,obj, "********"
312                   continue
313                if not nom in dico.keys(): dico[nom]={}
314                dico=dico[nom]
315             dico[nomMC]=valeur
316         self.texteComm=""
317         for etape in ordreEtapes :
318             print etape
319             if etape in self.dicoTexte.keys():
320                self.texteComm+=etape+"("
321                self.traiteEtape(self.dicoTexte[etape])
322                self.texteComm+=");\n"
323         print self.texteComm
324
325     def traiteEtape(self,dico):
326         for mc in dico.keys() :
327             valeur=dico[mc]
328             if isinstance(self.dicoNature[mc],Accas.A_SIMP.SIMP):
329                if 'TXM' in  self.dicoNature[mc].type and valeur[0] !="'" : valeur="'"+valeur
330                if 'TXM' in  self.dicoNature[mc].type and valeur[-1] !="'" : valeur=valeur+"'"
331                if 'Fichier' in  self.dicoNature[mc].type and valeur[0] !="'" : valeur="'"+valeur
332                if 'Fichier' in  self.dicoNature[mc].type and valeur[-1] !="'" : valeur=valeur+"'"
333                if 'Repertoire' in  self.dicoNature[mc].type and valeur[0] !="'" : valeur="'"+valeur
334                if 'Repertoire' in  self.dicoNature[mc].type and valeur[-1] !="'" : valeur=valeur+"'"
335                print self.dicoNature[mc].type
336                #self.texteComm+=mc+" = '"+str(valeur)+"',"
337                #else : self.texteComm+=mc+" = "+str(valeur)+","
338                self.texteComm+=mc+" = "+str(valeur)+","
339                continue
340             self.texteComm+=mc+"=_F("
341             self.traiteEtape(valeur)
342             self.texteComm+="),\n"