From b056af15b9fa9fe1d5f277a7abd7147a6638dd43 Mon Sep 17 00:00:00 2001 From: "pascale.noyret" Date: Wed, 16 Jun 2021 17:41:42 +0200 Subject: [PATCH] =?utf8?q?destruction=20inappropri=C3=A9e=20de=20convert?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- convert/__init__.py | 32 ++ convert/autre_parseur.py | 907 ++++++++++++++++++++++++++++++++++++++ convert/convert_XML.py | 75 ++++ convert/convert_dico.py | 100 +++++ convert/convert_map.py | 36 ++ convert/convert_python.py | 143 ++++++ convert/parseur_python.py | 696 +++++++++++++++++++++++++++++ 7 files changed, 1989 insertions(+) create mode 100644 convert/__init__.py create mode 100644 convert/autre_parseur.py create mode 100644 convert/convert_XML.py create mode 100644 convert/convert_dico.py create mode 100644 convert/convert_map.py create mode 100644 convert/convert_python.py create mode 100644 convert/parseur_python.py diff --git a/convert/__init__.py b/convert/__init__.py new file mode 100644 index 00000000..0a063d7a --- /dev/null +++ b/convert/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" + Ce package contient tous les convertisseurs de formats d'entree + en objets comprehensibles par EFICAS. + + Ces convertisseurs sont implementes sous forme de plugins +""" + +from __future__ import absolute_import +from Extensions import pluginloader + +import convert + +plugins=pluginloader.PluginLoader(convert) diff --git a/convert/autre_parseur.py b/convert/autre_parseur.py new file mode 100644 index 00000000..02428b5b --- /dev/null +++ b/convert/autre_parseur.py @@ -0,0 +1,907 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +from __future__ import absolute_import +from __future__ import print_function +try : + from future import standard_library + standard_library.install_aliases() +except : + pass +try : + from builtins import str +except : + pass +from builtins import object +import sys,re,tokenize +import io + + +class ENTITE_JDC(object) : + def __init__(self): + self.texte = '' + + def setText(self,texte): + self.texte = texte + + def appendText(self,texte): + """ + """ + self.texte = self.texte +texte + +class COMMENTAIRE(ENTITE_JDC): + + def __str__(self): + """ + Retourne une chaine de caracteres representant self + sous une forme interpretable par EFICAS + """ + t=repr(self.texte) + return "COMMENTAIRE(u"+t+")\n" + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant le # initial + """ + if texte[0] == '#': + self.texte = self.texte+texte[1:] + else: + # le diese n'est pas sur le premier caractere + amont,aval = texte.split('#',1) # on decoupe suivant la premiere occurrence de # + self.texte = self.texte +amont + aval + +class AFFECTATION(ENTITE_JDC): + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant tout retour chariot et tout point virgule + """ + self.texte = self.texte+texte + + def __str__(self): + """ + Retourne une expression de l'affectation comprehensible par ACCAS + et exploitable par EFICAS + """ + #t=repr(self.texte) + t=self.texte + return "PARAMETRE(nom='"+self.name+"',valeur="+t+")" + +class COMMANDE_COMMENTARISEE(ENTITE_JDC): + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant les doubles commentaires + """ + texte = texte.strip() + texte = texte[2:].strip() + self.texte = self.texte+(len(self.texte)>0)*'\n'+texte + + def __str__(self): + """ + Retourne une expression de la commande commentarisee comprehensible par ACCAS + et exploitable par EFICAS + """ + return "COMMANDE_COMM(texte="+repr(self.texte)+")\n" + + +next = {} +next['if'] = next['elif'] = 'elif', 'else', 'end' +next['while'] = next['for'] = 'else', 'end' +next['try'] = 'except', 'finally' +next['except'] = 'except', 'else', 'end' +next['else'] = next['finally'] = next['def'] = next['class'] = 'end' +next['end'] = () +start = 'if', 'while', 'for', 'try', 'def', 'class' + +class PARSEUR_PYTHON(object): + """ + Cette classe sert a creer un objet PARSEUR_PYTHON qui realise l'analyse d'un texte + representant un JDC Python en distinguant : + - les commentaires inter commandes + - les affectations + - les commandes + """ + # au moins 1 caractere non blanc ou non tabulation + #pattern_ligne_non_blanche = re.compile(r'^[\w\t]+') + pattern_ligne_non_blanche = re.compile(r'[^ \t]+') + kwprog = re.compile( + r'^\s*(?P[a-z]+)' + r'(\s+(?P[a-zA-Z_]\w*))?' + r'[^\w]') + endprog = re.compile( + r'^\s*#?\s*end\s+(?P[a-z]+)' + r'(\s+(?P[a-zA-Z_]\w*))?' + r'[^\w]') + wsprog = re.compile(r'^[ \t]*') + optionprog=re.compile(r'#\s*parse:\s*([^\n\'"]*)$') + + def __init__(self,texte): + # on verifie que le texte fourni se compile correctement + compile(texte,"",'exec') + self.texte = io.StringIO(texte) + self.line='' + self.out="" + self.lastcol = 0 + self.lastrow = 1 + self.please_indent = 1 + self.indent_list = [] + self.indentation=0 + self.paren_level=0 + self.affectation=0 + self.indent_list=[""] + self.objet_courant=None + self.affectation_flag=1 + self.comment_flag=1 + self.buffer=[] + self.buffer_indent="" + + def getOptions(self): + m= self.optionprog.match(self.line) + if m: + option=m.group(1) + name=option[1:] + flag=(option[0] == '+') + if name == "affectation": self.affectation_flag=flag + if name == "comment": self.comment_flag=flag + if name == "all": + self.comment_flag=flag + self.affectation_flag=flag + + def readline(self): + self.line= self.texte.readline() + #print "line:",self.line + # option ? + self.getOptions() + return self.line + + def getTexte(self,appliEficas=None): + """ + Retourne le texte issu de l'analyse + """ + for tk in tokenize.generate_tokens(self.readline): + self.processToken(tk) + return self.out + + def processToken(self, tk): + """ + """ + ttype, tstring, spos, epos, line = tk + thisrow, thiscol = spos + #print spos, epos,tokenize.tok_name[ttype],self.lastrow, self.lastcol + + if thisrow > self.lastrow: + # si plusieurs lignes (>1) + self.out=self.out+"\n" * (thisrow - self.lastrow - 1) + self.lastcol = 0 + +# if thiscol > self.lastcol : +# self.out=self.out+ " " * (thiscol - self.lastcol) +# self.please_indent = None + + self.thiscol=thiscol + #self.nextrow, self.nextcol = epos + + try: + fn = getattr(self, tokenize.tok_name[ttype]) + except AttributeError: + print( "No match!", tokenize.tok_name[ttype], tstring) + return + + if ttype != tokenize.DEDENT and ttype != tokenize.INDENT and self.please_indent: + self.doIndent() + + fn(tstring) + self.lastrow, self.lastcol = epos + + def output(self,tstring): + #print "output",tstring + + if self.thiscol > self.lastcol : + #print self.thiscol,self.lastcol + self.out=self.out+ " " * (self.thiscol - self.lastcol) + self.lastcol=self.thiscol + + self.out=self.out+tstring + + def outputCom(self,tstring): + self.out=self.out+tstring + + def updateIndent(self): + #print "updateIndent",len(self.indent_list[-1]),len(self.buffer_indent) + if len(self.indent_list[-1]) > len(self.buffer_indent): + self.out=self.out+(len(self.indent_list[-1]) - len(self.buffer_indent))*" " + self.buffer_indent=self.indent_list[-1] + + def doIndent(self): + #print "indentation dans doIndent",len(self.indent_list) + + self.out=self.out+self.indent_list[-1] + self.buffer_indent=self.indent_list[-1] + if self.lastcol+len(self.indent_list[-1]) > self.thiscol: + self.lastcol=self.thiscol + else: + self.lastcol=self.lastcol+len(self.indent_list[-1]) + self.please_indent = None + + def flush_buffer(self): + #if self.buffer: + # print len(self.indent_list),self.please_indent + for ob in self.buffer: + self.out= self.out+ str(ob) + self.doIndent() + self.buffer=[] + self.objet_courant=None + + def NL(self, tstring): + if self.affectation: + if self.paren_level == 0: + # affectation en cours mais complete + self.out= self.out+ str(self.affectation_courante) + self.affectation_courante=None + self.please_indent=1 + self.affectation=0 + else: + # affectation en cours, on ajoute + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + return + + if self.objet_courant: + self.objet_courant=None + self.buffer.append(tstring) + # self.please_indent = None + return + self.output(tstring) + self.please_indent = 1 + + def COMMENT(self, tstring): + liste= string.split(self.line,"##",1) + if len(liste) > 1: + # On a trouve un double commentaire + before,after=liste + if self.affectation: + # affectation en cours, on ignore + pass + elif self.paren_level > 0: + self.output(tstring) + elif self.comment_flag and not self.pattern_ligne_non_blanche.search(before): + # il s'agit d'une commande commentarisee + if self.objet_courant == None: + if not self.buffer:self.buffer_indent=self.indent_list[-1] + self.objet_courant=COMMANDE_COMMENTARISEE() + self.buffer.append(self.objet_courant) + self.objet_courant.appendText(tstring) + self.please_indent = None + elif isinstance(self.objet_courant,COMMENTAIRE): + self.objet_courant=COMMANDE_COMMENTARISEE() + self.buffer.append(self.objet_courant) + self.objet_courant.appendText(tstring) + self.please_indent = None + else: + self.objet_courant.appendText(tstring) + self.please_indent = None + else: + # commentaire inline + self.output(tstring) + self.please_indent = 1 + return + + else: + # On a un commentaire simple + new_line = self.line.split('#')[0] + if self.affectation: + # affectation en cours, on ignore + pass + elif self.paren_level > 0: + self.output(tstring) + elif self.comment_flag and not self.pattern_ligne_non_blanche.search(new_line): + # commentaire precede de blancs + if self.objet_courant == None: + if not self.buffer:self.buffer_indent=self.indent_list[-1] + self.objet_courant=COMMENTAIRE() + self.buffer.append(self.objet_courant) + self.objet_courant.appendText(tstring) + self.please_indent = None + elif isinstance(self.objet_courant,COMMANDE_COMMENTARISEE): + self.objet_courant=COMMENTAIRE() + self.buffer.append(self.objet_courant) + self.objet_courant.appendText(tstring) + self.please_indent = None + else: + self.objet_courant.appendText(tstring) + self.please_indent = None + else: + # commentaire inline + self.output(tstring) + self.please_indent = 1 + return + + def ERRORTOKEN(self, tstring): + print("ERRORTOKEN", tstring) + + def NAME(self, tstring): + if self.buffer: + self.updateIndent() + self.flush_buffer() + + if self.affectation ==1: + # on a une expression du type NAME=NAME + # on ne veut pas des expressions qui commencent par NAME=NAME(NAME= + # on en prend le chemin : on met affectation a 3 pour le signaler + # on attend d'en savoir plus + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=3 + return + elif self.affectation ==4: + # on a une expression qui commence par NAME=NAME(NAME + # il s'agit tres probablement d'une commande + # on annule l'affectation en cours + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=5 + return + elif self.affectation == 2: + # affectation en cours, on ajoute + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=2 + return + self.affectation=0 + self.name=None + if self.paren_level == 0 and self.affectation_flag: + # si on est en dehors de parentheses et en mode transformation d'affectation + # on initialise l'attribut name qui indique une affectation en cours + self.name=tstring + self.output(tstring) + + def ident(self, tstring): + self.flush_buffer() + self.affectation=0 + self.output(tstring) + + def NUMBER(self, tstring): + self.flush_buffer() + if self.affectation>=1: + # affectation en cours, on ajoute + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=2 + return + self.output(tstring) + + def OP(self,tstring): + self.flush_buffer() + if tstring in ('(','[','{'): self.paren_level=self.paren_level+1 + if tstring in (')',']','}'): self.paren_level=self.paren_level-1 + + if tstring == '=' and self.affectation ==5: + # on a une expression qui commence par NAME=NAME(NAME=) + # il peut s'agir d'une commande + # on annule l'affectation en cours + self.out= self.out+ self.affectation_courante.texte + self.affectation_courante=None + self.name=None + self.affectation=0 + elif tstring == ')' and self.affectation ==4: + # on a une expression qui commence par NAME=NAME() + # il peut s'agir d'une commande + # on annule l'affectation en cours + self.out= self.out+ self.affectation_courante.texte + self.affectation_courante=None + self.affectation=0 + elif tstring == '(' and self.affectation == 3: + # on a deja trouve NAME=NAME + # on passe affectation a 4 + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=4 + return + elif tstring == ';' and self.affectation>=1: + # l'affectation est terminee + self.out= self.out+ str(self.affectation_courante) + self.affectation_courante=None + self.please_indent=1 + self.affectation=0 + elif self.affectation>=1: + # on complete l'affectation + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=2 + return + + self.affectation=0 + if self.name and tstring=='=': + self.affectation=1 + self.affectation_courante=AFFECTATION() + self.affectation_courante.name=self.name + self.output(tstring) + + ENDMARKER = ident + NEWLINE=NL + + def INDENT(self, tstring): + #tstring=str(len(self.indent_list))*len(tstring) + self.indent_list.append(tstring) + #print "indentation dans INDENT",len(self.indent_list),len(tstring) + self.affectation=0 + if self.buffer: + self.updateIndent() + self.flush_buffer() + + def DEDENT(self, tstring): + #print "DEDENT",tstring,len(tstring) + if self.buffer: + self.out= self.out+ str(self.buffer[0]) + if len(self.buffer) > 1: + for ob in self.buffer[1:]: + self.doIndent() + self.out= self.out+ str(ob) + self.buffer=[] + self.objet_courant=None + self.please_indent=1 + + self.affectation=0 + self.indent_list = self.indent_list[:-1] + #print "indentation dans DEDENT",len(self.indent_list) + + def STRING(self, tstring): + self.flush_buffer() + if self.affectation>=1: + # affectation en cours, on ajoute + if self.thiscol > self.lastcol :self.affectation_courante.appendText((self.thiscol - self.lastcol)*" ") + self.affectation_courante.appendText(tstring) + self.affectation=2 + return + self.output(tstring) + +if __name__ == "__main__" : + import sys + import io + text=""" +# +# comment +# comment +# comment +# + +import sys,os + +# commentaire +# commentaire +# commentaire + +DEBUT(); +##toto = FORMULE(REEL='(REEL:A) = A',); + +x=2*cos(90.)/34. + +a=1. +if a != 0: + a=+1 + +b=2. +c=a+b +#if 1: +# d=3 +# e=5 +#try: +# a=1/2 +#except KeyError: +# pass + +if 1: + a=2 + b=3 + # commenta +else: + # commen + # commen + a=3 + #qqqqqqqqqqqqqqqqqqqqqqqq + c=5 + +b=5 + # commentaire +toto = FORMULE(REEL='(REEL:A) = A',); +titi = FORMULE(REEL='(REEL:A) = A',) # commentaire inline +tutu = FORMULE(REEL='(REEL:A) = A',) ## commentaire inline + +TEST_TABLE( TABLE=RELV[k], + FILTRE=( + _F( NOM_PARA = 'QUANTITE', + VALE_K = 'MAXIMUM'),), + # commentaire + NOM_PARA='VMIS', # comm + VALE=1.9669824189084E9, + REFERENCE='NON_REGRESSION', + VERSION='8.1.0' ) + +if 1: + a=fff(a=1, + b=2) +if 1: + a=2 + b=3 + # commenta +else: + # commen + # commen + a=3 + +for k in range(1,10): + + # Appel a GMSH pour le maillage + + f=open("coque.geo","w") + + +a = 1. +b=3 +c= 3 * 5 +d= 4 + \ + 5 \ + -4 +e=toto(a=1) +x=(1,2) +y=[3, +#comme +4] +z="a" +zz='v' +u='''aaaa +bbbb''' +if 1: + a=45 +else: + a=5.6 +d={"a":0} +e={"a":0, +#comme +"d":4} +a==1 +x=a==1 +s="-"*80 +fmt_raison='-'*80+''' + + Exception erreur_Fatale interceptee + Raison : %s + +'''+'-'*80+'xxxxxxxxxxxxxxxx' +q=30*cos(12) +f=cos(12) +#commen''' +#commen''' +y=a[1] +y=["x"]*10 + +##toto = FORMULE(REEL='(REEL:A) = A', +## X=2 +## ); +# +# comment +# comment +# comment +# +zz=8.9; +zz=8.9;aa=10 +P1 = 9.8; + +P2 = 8.8; + +P3 = 7; + +P5 = P3*P1; + +P6 = P1-3; + +P4 = [2,3,4]; + +P7=P4[1] +MA=LIRE_MAILLAGE() +MA=LIRE_MAILLAGE(#comment +) +xyz=cos(10) +MA=LIRE_MAILLAGE(INFO=1) +MA=LIRE_MAILLAGE( + NFO=1) +MA=LIRE_MAILLAGE(#comme + NFO=1) +MA=\ +LIRE_MAILLAGE(INFO=1) +MA= LIRE_MAILLAGE() +TFIN = 1.790 # Temps fin pour le calcul + +PAS = 0.001 # pas de temps du calcul +# parse: -affectation +DS1=[None]*5 +DS2=[None]*5 +DS3=[None]*5 +DS4=[None]*5 +CHS1=[None]*5 +CHS2=[None]*5 +MO=AFFE_MODELE( MAILLAGE=MA, + #test de validateur GEOM (typ=grma) avec grma derive de GEOM + AFFE=(_F(GROUP_MA = ('LI1'), + PHENOMENE = 'MECANIQUE', + MODELISATION = 'DIS_TR'), + ), + INFO=2,); + +for k in range(1,5): + DS1[k] = CREA_CHAMP( OPERATION='EXTR', TYPE_CHAM='NOEU_DEPL_R', + RESULTAT= MODESTA1, NUME_ORDRE=k, NOM_CHAM = 'DEPL'); + +# parse: +affectation +ff=23 # parametre bidon + +# parse: -all +a=45 +#commment1 +##toto = FORMULE(REEL='(REEL:A) = A', +## X=2 +## ); +# parse: +all +b=45 +#commment2 +##toto = FORMULE(REEL='(REEL:A) = A', +## X=2 +## ); +# parse: -comment +c=45 +#commment3 +##toto = FORMULE(REEL='(REEL:A) = A', +## X=2 +## ); +# parse: +comment +d=45 +#commment5 +##toto = FORMULE(REEL='(REEL:A) = A', +## X=2 +## ); +p=sin(ff) + +e=toto(a=1) +e=toto(a=1,b=3) +e=toto(1,b=3) +e=toto(a,b=3) +e=toto() +sensible=[2.1E11, 0.3, 1.E-6, 1.E-6, ] + +n=len(sensible) +# parse: -affectation + +PS=[None]*n + +for i in range(n): + PS[i]=DEFI_PARA_SENSI(VALE=sensible[i]) +# parse: +affectation + +TEST_RESU(RESU=(_F(RESULTAT = U3L, + INST = 1.0, + NOM_CHAM = 'DEPL', + GROUP_NO = 'PPA', + NOM_CMP = 'DX', + VALE = 2.86E-5, + PRECISION = 5.E-2, + REFERENCE = 'AUTRE_ASTER', + VERSION = '7.1.11', + ), + ) + )# +# +FIN() +# + +TEST_RESU(RESU=(_F(RESULTAT = U3L, + INST = 1.0, + NOM_CHAM = 'DEPL', + GROUP_NO = 'PPA', + NOM_CMP = 'DX', + VALE = 2.86E-5, + PRECISION = 5.E-2, + REFERENCE = 'AUTRE_ASTER', + VERSION = '7.1.11', + ), + ) + ) #a + +titi = FORMULE(REEL='(REEL:A) = A', +) # commentaire inline +titi = FORMULE(REEL='(REEL:A) = A', + ) # commentaire inline + +def f(x):return x +#comment +def f(x): +#comment + for i in range(10): s=0 + +#com1 +#com2 + +#com3 +a=1 +##commendcomm +for k in range(1,10): + + # Appel a GMSH pour le maillage + + f=open("coque.geo","w") +#comm + if a==1: + + #comm + + for i in x: +#comm +##commendcomm +#comm +##commendcomm +#comm + if x==3: +#comm + r=1 + if w==4: +#comm + + if k: + +#comm + if g: + +#comm + + if t: + a=5 +#comm +if 1: + a=2 + b=3 + # commenta +else: + # commen + # commen + a=3 + # qqqqqqqqqqqqqqqq + c=5 + +b=5 + +if 1: + a=2 + # commenta +else: + a=3 +if 1: + if 2: + if 3: + a=1 + elif 4: + b=1 + else: + c=5 + elif 3: + x=1 + else: + y=4 +elif 4: + s=1 +else: + t=9 +#com1 +#com2 + +#com3 +a=1 +##commendcomm +for k in range(1,10): + + # Appel a GMSH pour le maillage + + f=open("coque.geo","w") +#comm + if 1: + if 2: + if 3: + a=1 + else: + a=6 +a=1 +##commendcomm +for k in range(1,10): + + # Appel a GMSH pour le maillage + + f=open("coque.geo","w") +#comm + + if a==1: + + #comm + + for i in x: +#comm +##commendcomm +#comm +##commendcomm +#comm + if x==3: +#comm + r=1 + + if 1: + if 2: + if 3: + a=1 + else: + a=6 + +if 1: + if 2: + if 3: + r=1 + # comm + else: + x=7 + toto(a=1, +b=3) +SUP_=dict([(grand,0.) for grand in grand_obs]) + +for k in range(1,ns+1): + x=toto(a=1,b=2) +# comm + if 1: + #com + + #com + x=1 + #com + + #com + ##com + elif 3: + ##com + x=1 + else: + y=3 + +def f(): + return +######################################################################## + +######################################################################## +# macro commande de post-traitement (ex POST_GOUJ2E) +# calcul des reactions cumulees suivant les filets + +def POST_GOUJ_ops(self,TABLE): + ier=0 + +""" + if len(sys.argv)== 2: + progname, input = sys.argv + f=open(input) + t=f.read() + f.close() + else: + t=text + txt = PARSEUR_PYTHON(t).getTexte() + print (txt) + compile(txt,"",'exec') diff --git a/convert/convert_XML.py b/convert/convert_XML.py new file mode 100644 index 00000000..7a6be7b0 --- /dev/null +++ b/convert/convert_XML.py @@ -0,0 +1,75 @@ +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +from __future__ import absolute_import + + +import re +from Extensions.i18n import tr + +#import traceback +#traceback.print_stack() + +from Extensions import localisation +from Noyau import N_CR + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return { + 'name' : 'xml', + 'factory' : XMLparser + } + +class XMLparser: + """ + This converter works like Pythonparser, except that it is supposed to read XML + """ + + def __init__(self,cr=None): + print ('dans XML convert') + self.text='' + if cr : self.cr=cr + else: self.cr=N_CR.CR(debut='CR convertisseur format XML', + fin='fin CR format XML') + + def readfile(self,filename): + self.filename=filename + try: + with open(filename) as fd : + self.text=fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + return + + + + def convert(self, outformat, appliEficas=None): + # ici on ne fait rien + # on le fera a la creation du JDC + try: + return self.text + except EficasException: + # Erreur lors de la conversion + l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1], + sys.exc_info()[2]) + self.cr.exception(tr("Impossible de convertir le fichier XML\n %s", ''.join(l))) + return "" diff --git a/convert/convert_dico.py b/convert/convert_dico.py new file mode 100644 index 00000000..c2996a0b --- /dev/null +++ b/convert/convert_dico.py @@ -0,0 +1,100 @@ +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +from __future__ import absolute_import + + +from Extensions.i18n import tr +from Extensions import localisation + + +from .convert_python import Pythonparser +from Noyau import N_CR + +try: + basestring +except NameError: + basestring = str + + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return { + 'name' : 'dico', + 'factory' : Dicoparser + } + +class Dicoparser(Pythonparser): + """ + This converter initializes model variable from a python dictionnary + """ + + def __init__(self,cr=None): + # Si l'objet compte-rendu n'est pas fourni, on utilise le + # compte-rendu standard + self.text='' + self.textePy='' + if cr : + self.cr=cr + else: + self.cr=N_CR.CR(debut='CR convertisseur format dico', + fin='fin CR format dico') + + def readfile(self,filename): + self.filename=filename + try: + with open(filename) as fd : + self.text=fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + return + + def convert(self,outformat,appli=None): + monTexteDico={} + exec (self.text,globals(),monTexteDico) + if len(monTexteDico.keys()) != 1 : + self.cr.exception(tr("Impossible de traiter le fichier %s" ,str(filename))) + self.cr.fatal(tr("Impossible de traiter le fichier %s" ,str(filename))) + return + self.textePy="" + monDico=monTexteDico[monTexteDico.keys()[0]] + for commande in monDico : + valeurs=monDico[commande] + if valeurs.has_key('NomDeLaSdCommande') : + # cas d un oper + self.textePy+=valeurs['NomDeLaSdCommande']+' = '+commande+'(' + del valeurs['NomDeLaSdCommande'] + else : + self.textePy+=commande+'(' + for mot in valeurs : + if isinstance(valeurs[mot],dict) : self.traiteMCFact(mot,valeurs[mot]) + else : self.textePy += mot+' = ' +str(valeurs[mot])+',' + self.textePy+=');\n' # fin de la commande + #print (self.textePy) + return self.textePy + + def traiteMCFact(self,mot,valeurs): + self.textePy += mot + '=_F(' + for mot in valeurs : + if isinstance(valeurs[mot],dict) : self.traiteMCFact(mot,valeurs[mot]) + else : self.textePy +=mot+' = ' +str(valeurs[mot])+',' + self.textePy +='),' diff --git a/convert/convert_map.py b/convert/convert_map.py new file mode 100644 index 00000000..f36a0b3a --- /dev/null +++ b/convert/convert_map.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" +""" + +from __future__ import absolute_import +from .convert_python import Pythonparser + +def entryPoint(): + """ + Retourne les informations necessaires pour le chargeur de plugins + Ces informations sont retournees dans un dictionnaire + """ + return { + # Le nom du plugin + 'name' : 'MAP', + # La factory pour creer une instance du plugin + 'factory' : Pythonparser, + } diff --git a/convert/convert_python.py b/convert/convert_python.py new file mode 100644 index 00000000..535dfaf4 --- /dev/null +++ b/convert/convert_python.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" + Ce module contient le plugin convertisseur de fichier + au format python pour EFICAS. + + Un plugin convertisseur doit fournir deux attributs de classe : + extensions et formats et deux methodes : readfile,convert. + + L'attribut de classe extensions est une liste d'extensions + de fichiers preconisees pour ce type de format. Cette information + est seulement indicative. + + L'attribut de classe formats est une liste de formats de sortie + supportes par le convertisseur. Les formats possibles sont : + eval, dict ou exec. + Le format eval est un texte source Python qui peut etre evalue. Le + resultat de l'evaluation est un objet Python quelconque. + Le format dict est un dictionnaire Python. + Le format exec est un texte source Python qui peut etre execute. + + La methode readfile a pour fonction de lire un fichier dont le + nom est passe en argument de la fonction. + - convertisseur.readfile(nom_fichier) + + La methode convert a pour fonction de convertir le fichier + prealablement lu dans un objet du format passe en argument. + - objet=convertisseur.convert(outformat) + + Ce convertisseur supporte le format de sortie exec + +""" +from __future__ import absolute_import +try : + from builtins import str + from builtins import object +except : + pass +import sys,traceback + +from .parseur_python import PARSEUR_PYTHON +from Noyau import N_CR +from Extensions.i18n import tr +from Extensions.eficas_exception import EficasException + +def entryPoint(): + """ + Retourne les informations necessaires pour le chargeur de plugins + Ces informations sont retournees dans un dictionnaire + """ + return { + # Le nom du plugin + 'name' : 'python', + # La factory pour creer une instance du plugin + 'factory' : Pythonparser, + } + + +class Pythonparser(object): + """ + Ce convertisseur lit un fichier au format python avec la + methode readfile : convertisseur.readfile(nom_fichier) + et retourne le texte au format outformat avec la + methode convertisseur.convert(outformat) + + Ses caracteristiques principales sont exposees dans 2 attributs + de classe : + - extensions : qui donne une liste d'extensions de fichier preconisees + - formats : qui donne une liste de formats de sortie supportes + """ + # Les extensions de fichier preconisees + extensions=('.py',) + # Les formats de sortie supportes (eval dict ou exec) + # Le format exec est du python executable (commande exec) converti avec PARSEUR_PYTHON + # Le format execnoparseur est du python executable (commande exec) non converti + formats=('exec','execnoparseur') + + def __init__(self,cr=None): + # Si l'objet compte-rendu n'est pas fourni, on utilise le + # compte-rendu standard + self.text='' + if cr : + self.cr=cr + else: + self.cr=N_CR.CR(debut='CR convertisseur format python', + fin='fin CR format python') + + def readfile(self,filename): + self.filename=filename + try: + with open(filename) as fd : + self.text=fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s" ,str(filename))) + return + + def convert(self,outformat,appliEficas=None): + if outformat == 'exec': + try: + #import cProfile, pstats, StringIO + #pr = cProfile.Profile() + #pr.enable() + l= PARSEUR_PYTHON(self.text).getTexte(appliEficas) + + #pr.disable() + #s = StringIO.StringIO() + #sortby = 'cumulative' + #ps = pstats.Stats(pr, stream=s).sort_stats(sortby) + #ps.print_stats() + #print (s.getValue()) + + return l + except EficasException: + # Erreur lors de la conversion + l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1], + sys.exc_info()[2]) + self.cr.exception(tr("Impossible de convertir le fichier Python qui doit contenir des erreurs.\n\ + On retourne le fichier non converti. Prevenir la maintenance.\n\n %s", ''.join(l))) + # On retourne neanmoins le source initial non converti (au cas ou) + return self.text + elif outformat == 'execnoparseur': + return self.text + else: + raise EficasException(tr("Format de sortie : %s, non supporte", outformat)) + return None diff --git a/convert/parseur_python.py b/convert/parseur_python.py new file mode 100644 index 00000000..19d73256 --- /dev/null +++ b/convert/parseur_python.py @@ -0,0 +1,696 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +from __future__ import absolute_import +from __future__ import print_function +try : + from builtins import str + from builtins import object +except : + pass +import sys,string,re +import traceback +from Extensions.i18n import tr + +escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')") +stringsAndCommentsRE = \ + re.compile(u"(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL) +#stringsAndCommentsRE = \ +# re.compile(u"(\"\"\".*\"\"\"|'''.*'''|\"[^\"]*\"|\'[^\']*\'|#.*\n)", re.DOTALL) +import six +if six.PY2 : + allchars = string.maketrans(u"", "") + allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:] + allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline)) +else : + allchars=bytes.maketrans(b"",b"") + allcharsExceptNewline = allchars[: allchars.index(b'\n')]+allchars[allchars.index(b'\n')+1:] + allcharsExceptNewlineTranstable = bytes.maketrans(allcharsExceptNewline, b'*'*len(allcharsExceptNewline)) + +#if sys.platform[0:5]=="linux" : +# allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline)) +#elif sys.platform[0:3]=="win" : +# allcharsExceptNewlineTranstable = dict((ord(char), u'*') for char in allcharsExceptNewline)# +#else : +# allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline)) + +def maskStringsAndComments(src): + """Masque tous les caracteres de src contenus dans des commentaires ou des strings multilignes (triples + quotes et guillemets. + Le masquage est realise en remplacant les caracteres par des * + Attention : cette fonction doit etre utilisee sur un texte complet et pas ligne par ligne + """ +# remplace les \\, les \" les \' par ** +# supprime toutes les chaines ou commentaires ,y compris multiligne i +# entre 3 ou 1 simples ou doubles quotes (ouvrantes fermantes) ou # +# laisse les non fermantes ou non ouvrantes +# on prend 1 sur 2 en raison du split qui donne python, commentaire, python, commentaire... + + src = escapedQuotesRE.sub("**", src) + allstrings = stringsAndCommentsRE.split(src) + + # on a une liste d elements constituee successivement de (string, comment) + for i in range(1, len(allstrings), 2): + if allstrings[i].startswith(u"'''")or allstrings[i].startswith('"""'): + allstrings[i] = allstrings[i][:3]+ \ + allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \ + allstrings[i][-3:] + else: + allstrings[i] = allstrings[i][0]+ \ + allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \ + allstrings[i][-1] + + return "".join(allstrings) + +implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}')) +linecontinueRE = re.compile(r"\\\s*(#.*)?$") +emptyHangingBraces = [0,0,0,0,0] + +class parserException(Exception): pass +class FatalError(Exception): pass + +#commentaire double precede d'un nombre quelconque de blancs (pas multiligne) +pattern_2comments = re.compile(r"^\s*##.*") +pattern_finComments = re.compile("^\s*##Fin Commentaire") +#commentaire standard precede d'un nombre quelconque de blancs (pas multiligne) +pattern_comment = re.compile(r"^\s*#.*") +#fin de ligne ; suivi d'un nombre quelconque de blancs (pas multiligne) +pattern_fin = re.compile(r"; *$") +#pattern pour supprimer les blancs, tabulations et fins de ligne +pattern_blancs = re.compile(r"[ \t\r\f\v]") +#pattern_blancs = re.compile(r"[\s\n]") +number_kw_pattern=re.compile(r""" +( + #groupe nombre decimal + (?: + #signe : on ignore le signe + + [-]? + #groupe (avec ?: n'apparait pas en tant que groupe dans le resultat) + (?: + #mantisse forme entiere.fractionnaire + \d+(?:\.\d*)? + | + #ou forme .fractionnaire + \.\d+ + ) + (?:[eE][+-]?\d+)? + ) + | + #argument keyword + [a-zA-Z_]\w*= +) +""",re.VERBOSE|re.MULTILINE) + +def construitGenea(texte,listeMc): + """ + Retourne un dictionnaire dont les cles sont des reels et les valeurs sont leurs representations textuelles. + + Realise un filtrage sur les reels : + + - Ne garde que les reels pour lesquels str ne donne pas une bonne representation. + - Ne garde que les reels derriere un argument keyword dont le nom est dans listeMc + + >>> 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), + ... #POMPE_PRIMA._BOUCLE_N._2_ELEMENT_NUMERO:0239 + ... h=_F(x=34.6,y=-1)''' + >>> construitGenea(s,['a','x']) + {0.000213: '21.3e-5'} + """ + d={} + mot="" + #on masque les strings et commentaires pour ne pas identifier de faux reels + for m in number_kw_pattern.findall(maskStringsAndComments(texte)): + if m[-1] == '=': + #argument keyword + mot=m[:-1] + else: + if mot not in listeMc:continue + #valeur + key=eval(m) + if str(key) != m: d[key]=m + return d + + +class ENTITE_JDC(object) : + """Classe de base pour tous les objets crees lors de la conversion + Tout objet derive est enregistre aupres de son pere a sa creation + """ + def __init__(self,pere): + self.texte = '' + pere.l_objets.append(self) + + def setText(self,texte): + self.texte = texte + + def appendText(self,texte): + """ + Ajoute texte a self.texte en mettant un retour chariot a la fin de texte + """ + texte = texte+'\n' + self.texte = self.texte +texte + + def __str__(self): + return self.texte + +class COMMENTAIRE(ENTITE_JDC): + + def __str__(self): + """ + Retourne une chaine de caracteres representants self + sous une forme interpretable par EFICAS + """ + t=repr(self.texte) + return "COMMENTAIRE(u"+t+")\n" + + #s='COMMENTAIRE(u"""'+self.texte+'""")\n\n' + #return s + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant le # initial + """ + texte = texte+'\n' + if texte[0] == '#': + self.texte = self.texte+texte[1:] + else: + # le diese n'est pas sur le premier caractere + amont,aval = texte.split('#',1) # on decoupe suivant la premiere occurrence de # + self.texte = self.texte +amont + aval + +class COMMANDE(ENTITE_JDC): + + def __str__(self): + """ + Retourne self.texte + """ + return self.texte+'\n' + + def getNbPar(self): + """ + Retourne la difference entre le nombre de parentheses ouvrantes + et le nombre de parentheses fermantes presentes dans self.texte + Peut donc retourner un entier negatif + """ + # faire attention aux commentaires contenus dans self.texte + # qui peuvent eux-memes contenir des parentheses !!!! + l_lignes = self.texte.split('\n') + nb = 0 + for ligne in l_lignes: + ligne = ligne.split('#')[0] + #nb = nb + (string.count(ligne,'(')-string.count(ligne,')')) + + nb = nb + ( ligne.count('(') - ligne.count(')') ) + return nb + +class AFFECTATION(ENTITE_JDC): + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant tout retour chariot et tout point virgule + PN et tout commentaire + """ + if texte[-1] == '\n' : texte = texte[0:-1].rstrip() + if texte[-1] == ';' : texte = texte[0:-1].rstrip() + self.texte = self.texte+texte+'\n' + + def __str__(self): + """ + Retourne une expression de l'affectation comprehensible par ACCAS + et exploitable par EFICAS + """ + nom,valeur = self.texte.split('=',1) + n = nom.rstrip() + nom = n.lstrip() + if valeur[-1] == '\n': valeur = valeur[:-1] + return n + ' = PARAMETRE(nom=\''+nom+'\',valeur='+valeur+')\n' + +class COMMANDE_COMMENTARISEE(ENTITE_JDC): + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant les doubles commentaires + """ + texte = texte.strip() + texte = texte[2:].strip() + self.texte = self.texte+(len(self.texte)>0)*'\n'+texte + + def __str__(self): + """ + Retourne une expression de la commande commentarisee comprehensible par ACCAS + et exploitable par EFICAS + """ + return "COMMANDE_COMM(texte="+repr(self.texte)+")\n" + #return "COMMANDE_COMM(texte='''"+self.texte+"''')\n" + +class AFFECTATION_EVAL(ENTITE_JDC): + + def appendText(self,texte): + """ + Ajoute texte a self.texte en enlevant tout retour chariot + """ + if texte[-1] == '\n' : texte = texte[1:-1] + self.texte = self.texte+texte + + def __str__(self): + """ + Retourne une expression du parametre EVAL comprehensible par ACCAS + et exploitable par EFICAS + """ + nom,valeur = self.texte.split('=',1) + nom = nom.strip() + if valeur[-1] == '\n': valeur = valeur[:-1] + valeur = valeur.strip() + return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n' + +class PARSEUR_PYTHON(object): + """ + Cette classe sert a generer un objet PARSEUR_PYTHON qui realise l'analyse d'un texte + representant un JDC Python en distinguant : + - les commentaires inter commandes + - les affectations + - les commandes + """ + pattern_commande = re.compile(r'^([A-Z][a-zA-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)') + pattern_eval = re.compile(r'^(EVAL)([ \t\r\f\v]*)\(([\w\W]*)') + pattern_ligne_vide = re.compile(r'^[\t\r\f\v\n]+') + pattern_name = re.compile(r'[a-zA-Z_]\w*') + + def __init__(self,texte): + self.texte = texte + self.l_objets=None + self.appliEficas=None + + def isAffectation(self,texte): + """ + Methode booleenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes + Aster, 0 sinon + """ + if '=' not in texte : return 0 + if self.pattern_commande.match(texte): + # cas d'une procedure ... + return 0 + amont,aval = texte.split('=',1) + aval = aval.strip() + + + if self.pattern_commande.match(aval): + return 0 + else: + s= amont.strip() + m= self.pattern_name.match(s) + if m is None : return 0 + if m.start() != 0 :return 0 + if m.end() != len(s):return 0 + return 1 + + def isEval(self,texte): + """ + Methode booleenne qui retourne 1 si le texte est celui d'une affectation de type EVAL + dans un jeu de commandes Aster, 0 sinon + """ + if '=' not in texte : return 0 + if self.pattern_commande.match(texte): + # cas d'une procedure ... + return 0 + amont,aval = texte.split('=',1) + aval = aval.strip() + if not self.pattern_commande.match(aval) : return 0 + if self.pattern_eval.match(aval): + return 1 + else: + return 0 + + def isCommande(self,texte): + """ + Methode booleenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes + Aster, 0 sinon + """ + if self.pattern_commande.match(texte): + # cas d'une procedure ... + return 1 + # A ce stade il faut avoir un OPER ou une MACRO, bref un '=' ! + if '=' not in texte : return 0 + # on a un texte de la forme xxxx = yyyyy + # --> reste a analyser yyyy + amont,aval = texte.split('=',1) + aval = aval.strip() + if self.pattern_commande.match(aval): + return 1 + else: + return 0 + + def isModificationCatalogue(self,texte) : + if self.pattern_commande.match(texte): + return 1 + + def analyse(self): + """ + Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions + et de commentaires (parmi lesquels des instructions "commentarisees"). + """ + l_lignes = self.texte.split('\n') + commentaire_courant = None + commande_courante = None + affectation_courante = None + commande_commentarisee_courante = None + self.l_objets = [] + + #initialisation du nombre de parentheses non fermees et de commentaires non termines + #Attention a reinitialiser en fin de ligne logique + #Une ligne logique peut s'etendre sur plusieurs lignes physiques avec des caracteres de continuation + #explicites ou implicites + hangingBraces = list(emptyHangingBraces) + hangingComments = 0 + + #Masquage des commentaires et strings multilignes + srcMasked=maskStringsAndComments('\n'.join(l_lignes)) + masked_lines=srcMasked.split('\n') + lineno=0 + + for ligne in l_lignes : + line=masked_lines[lineno] + lineno=lineno+1 + #print ("ligne:",line) + # mise a jour du nombre total de parentheses ouvertes (non fermees) + # et du nombre de commentaires non termines + for i in range(len(implicitContinuationChars)): + contchar = implicitContinuationChars[i] + numHanging = hangingBraces[i] + hangingBraces[i] = numHanging+line.count(contchar[0]) - line.count(contchar[1]) + + hangingComments ^= line.count('"""') % 2 + hangingComments ^= line.count(u"'''") % 2 + #print (hangingComments,hangingBraces) + if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0: + raise parserException() + + if ligne.strip() == '': + # il s'agit d'un saut de ligne + # --> on l'ignore + continue + + if pattern_2comments.match(ligne): + #on a trouve une commande commentarisee : double commentaire sans rien devant a part des blancs + if commentaire_courant: + #Si un commentaire ordinaire est en cours on le termine + commentaire_courant = None + + if commande_courante : + # on a un objet commentarise a l'interieur d'une commande + # --> non traite pour l'instant : on l'ajoute simplement a la commande courante comme + # un commentaire ordinaire + commande_courante.appendText(ligne) + elif commande_commentarisee_courante : + # commande_commentarisee en cours : on ajoute la ligne + commande_commentarisee_courante.appendText(ligne) + # on a 2 commandes commentarisees de suite + if pattern_finComments.match(ligne) : + commande_commentarisee_courante = None + else: + # debut de commande commentarisee : on cree un objet commande_commentarisee_courante + commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self) + commande_commentarisee_courante.appendText(ligne) + + #on passe a la ligne suivante + continue + + if pattern_comment.match(ligne): + #commentaire ordinaire avec seulement des blancs devant + if commande_commentarisee_courante : + # commande_commentarisee en cours : on la clot + commande_commentarisee_courante = None + + if commande_courante : + # il s'agit d'un commentaire a l'interieur d'une commande --> on ne fait rien de special + #on l'ajoute au texte de la commande + commande_courante.appendText(ligne) + elif commentaire_courant : + # il s'agit de la nieme ligne d'un commentaire entre deux commandes + # --> on ajoute cette ligne au commentaire courant + commentaire_courant.appendText(ligne) + else : + # il s'agit d'un nouveau commentaire entre deux commandes + # --> on le cree et il devient le commentaire courant + commentaire_courant = COMMENTAIRE(self) + commentaire_courant.appendText(ligne) + + #on passe a la ligne suivante + continue + + # la ligne contient des donnees autre qu'un eventuel commentaire + if commentaire_courant : + # on clot un eventuel commentaire courant + commentaire_courant = None + + if commande_commentarisee_courante : + # on clot une eventuelle commande commentarisee courante + commande_commentarisee_courante = None + + if commande_courante : + #on a une commande en cours. On l'enrichit ou on la termine + commande_courante.appendText(ligne) + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #la commande est terminee + self.analyseReel(commande_courante.texte) + commande_courante = None + + #on passe a la ligne suivante + continue + + if affectation_courante != None : + #poursuite d'une affectation + affectation_courante.appendText(ligne) + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #L'affectation est terminee + affectation_courante=None + #on passe a la ligne suivante + continue + + # il peut s'agir d'une commande ou d'une affectation ... + # ou d'un EVAL !!! + if self.isEval(ligne): + # --> affectation de type EVAL + if affectation_courante : affectation_courante = None + affectation = AFFECTATION_EVAL(self) + affectation.appendText(ligne) + #on passe a la ligne suivante + continue + + if self.isAffectation(ligne): + #print( '--> affectation') + text=ligne + #traitement des commentaires en fin de ligne + compos=line.find(u"#") + if compos > 2: + #commentaire en fin de ligne + #on cree un nouveau commentaire avant le parametre + COMMENTAIRE(self).appendText(ligne[compos:]) + text=ligne[:compos] + #si plusieurs instructions separees par des ; sur la meme ligne + inspos=line.find(u";") + if inspos > 2: + #on garde seulement la premiere partie de la ligne + #si on a que des blancs apres le point virgule + if text[inspos:].strip() == ";": + text=text[:inspos] + else: + raise FatalError(tr("Eficas ne peut pas traiter plusieurs instructions \ + sur la meme ligne : %s", ligne)) + + affectation_courante = AFFECTATION(self) + affectation_courante.appendText(text) + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #L'affectation est terminee + affectation_courante=None + #on passe a la ligne suivante + continue + + if self.isCommande(ligne): + # --> nouvelle commande + affectation_courante = None + commande_courante = COMMANDE(self) + commande_courante.appendText(ligne) + #si la commande est complete, on la termine + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #la commande est terminee + self.analyseReel(commande_courante.texte) + commande_courante = None + #on passe a la ligne suivante + continue + + + def enleve (self,texte) : + """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations + Le nouveau texte est retourne + """ + i=0 + chaine="" + while (i', 'exec') + print((a.dict_reels)) -- 2.39.2