]> SALOME platform Git repositories - tools/eficas.git/commitdiff
Salome HOME
destruction inappropriée de convert
authorpascale.noyret <pascale.noyret@edf.fr>
Wed, 16 Jun 2021 15:41:42 +0000 (17:41 +0200)
committerpascale.noyret <pascale.noyret@edf.fr>
Wed, 16 Jun 2021 15:41:42 +0000 (17:41 +0200)
convert/__init__.py [new file with mode: 0644]
convert/autre_parseur.py [new file with mode: 0644]
convert/convert_XML.py [new file with mode: 0644]
convert/convert_dico.py [new file with mode: 0644]
convert/convert_map.py [new file with mode: 0644]
convert/convert_python.py [new file with mode: 0644]
convert/parseur_python.py [new file with mode: 0644]

diff --git a/convert/__init__.py b/convert/__init__.py
new file mode 100644 (file)
index 0000000..0a063d7
--- /dev/null
@@ -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 (file)
index 0000000..02428b5
--- /dev/null
@@ -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<kw>[a-z]+)'
+                r'(\s+(?P<id>[a-zA-Z_]\w*))?'
+                r'[^\w]')
+    endprog = re.compile(
+                r'^\s*#?\s*end\s+(?P<kw>[a-z]+)'
+                r'(\s+(?P<id>[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,"<string>",'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,"<string>",'exec')
diff --git a/convert/convert_XML.py b/convert/convert_XML.py
new file mode 100644 (file)
index 0000000..7a6be7b
--- /dev/null
@@ -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 (file)
index 0000000..c2996a0
--- /dev/null
@@ -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 (file)
index 0000000..f36a0b3
--- /dev/null
@@ -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 (file)
index 0000000..535dfaf
--- /dev/null
@@ -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 (file)
index 0000000..19d7325
--- /dev/null
@@ -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<len(texte)):
+            if (texte[i] == " " or texte[i] == "\n" or texte[i] == "\t") :
+                i=i+1
+            else :
+                chaine=chaine+texte[i]
+                i=i+1
+        return chaine
+
+    def construitGenea(self,texte):
+        indiceC=0
+        mot=""
+        dict_reel_concept={}
+
+        # traitement pour chaque caractere
+        while (indiceC < len(texte)):
+            c=texte[indiceC]
+            if ( c == "," or c == "(u" or c == ")"):
+                mot=""
+            elif ( c== "="):
+                #on doit trouver derriere soit une valeur soit une parenthese
+                valeur=""
+                nouvelindice=indiceC+1
+                if texte[nouvelindice] != "(u":
+                    #pas de parenthese ouvrante derriere un signe =, on a une valeur.
+                    while ( texte[nouvelindice] != "," and texte[nouvelindice] != ")"):
+                        valeur=valeur+texte[nouvelindice]
+                        nouvelindice=nouvelindice+1
+                        if nouvelindice == len(texte) :
+                            nouvelindice=nouvelindice -1
+                            break
+                    if mot in self.appliEficas.liste_simp_reel:
+                        if valeur[0] != "'":
+                            try :
+                                clef=eval(valeur)
+                                if str(clef) != str(valeur) :
+                                    dict_reel_concept[clef]=valeur
+                            except :
+                                pass
+                    mot=""
+                    indiceC=nouvelindice
+                else:
+                    #parenthese ouvrante derriere un signe =, on a un tuple de valeur ou de mots cles facteurs.
+                    # s agit -il d un tuple
+                    if texte[nouvelindice+1] != "(u":
+                        #le suivant n'est pas une parenthese ouvrante : on a un tuple de valeurs ou un mot cle facteur
+                        tuple=False
+                        #on avance jusqu'a la fin du tuple de valeurs ou jusqu'a la fin du premier mot cle simple
+                        #contenu dans le mot cle facteur
+                        while ( texte[nouvelindice] != "="):
+                            if texte[nouvelindice] == ")" :
+                                tuple=True
+                                break
+                            else :
+                                nouvelindice=nouvelindice+1
+                                if nouvelindice == len(texte) :
+                                    nouvelindice=nouvelindice -1
+                                    break
+                        if tuple :
+                            #cas du tuple de valeurs
+                            valeur=texte[indiceC+1:nouvelindice+1]
+                            indiceC=nouvelindice+1
+                            if mot in self.appliEficas.liste_simp_reel:
+                                valeur=valeur[1:-1]
+                                for val in valeur.split(',') :
+                                # Attention la derniere valeur est""
+                                    try :
+                                        if val[0] != "'":
+                                            clef=eval(val)
+                                            if str(clef) != str(val) :
+                                                dict_reel_concept[clef]=val
+                                    except :
+                                        pass
+                            mot=""
+                    # ou de ( imbriquees
+                    else :
+                        #cas du mocle facteur simple ou
+                        mot=""
+            else :
+                mot=mot+texte[indiceC]
+            indiceC=indiceC+1
+        # traitement du dernier inutile
+        # c est un ;
+        return dict_reel_concept
+
+    def analyseReel(self,commande) :
+        nomConcept=None
+        # On verifie qu on a bien un OPER
+        # et pas une MACRO
+        if commande.find(u"=") > commande.find(u"(u") :
+            return
+        if commande.find(u"=") > 0:
+            #epure1=self.enleve(commande)
+            epure1=pattern_blancs.sub(u"",commande)
+            nomConcept,corps=epure1.split(u"=",1)
+            epure2=corps.replace(u"_F(u","(u")
+            #nomConcept=epure1.split(u"=")[0]
+            #index=epure1.find(u"=")
+            #epure2=epure1[index+1:len(epure1)].replace(u"_F(u","(u")
+            #dict_reel_concept=self.construitGenea(epure2)
+            if self.appliEficas:
+                dict_reel_concept=construitGenea(epure2,self.appliEficas.liste_simp_reel)
+            else:
+                dict_reel_concept={}
+        if nomConcept == "sansnom" :
+            nomConcept = ""
+        if nomConcept !=None :
+            if len(dict_reel_concept) != 0:
+                self.appliEficas.dict_reels[nomConcept]=dict_reel_concept
+
+    def getTexte(self,appliEficas=None):
+        """
+        Retourne le texte issu de l'analyse
+        """
+        self.appliEficas=appliEficas
+        try:
+        #if 1:
+            if not self.l_objets : self.analyse()
+            txt=''
+            for obj in self.l_objets:
+                txt = txt+str(obj)
+        #else :
+        except  parserException:
+            #Impossible de convertir le texte, on le retourne tel que
+            txt=self.texte
+        return txt
+
+def test():
+    #import parseur_python
+    import doctest
+    doctest.testmod(parseur_python)
+
+
+if __name__ == "__main__" :
+    import time
+    #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
+    #fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
+    with open(fichier) as fd:
+        texte = fd.read()
+    class appliEficas(object):
+        dict_reels={}
+        liste_simp_reel=["VALE","VALE_C","GROUP_MA","RAYON"]
+    a=appliEficas()
+
+    compile(txt, '<string>', 'exec')
+    print((a.dict_reels))