]> SALOME platform Git repositories - modules/eficas.git/commitdiff
Salome HOME
CCAR: 3 modifications V1_10b3
authorChristian Caremoli <>
Tue, 20 Jun 2006 08:50:30 +0000 (08:50 +0000)
committerChristian Caremoli <>
Tue, 20 Jun 2006 08:50:30 +0000 (08:50 +0000)
modif 1 : suppression de l'appel au parseur dans INCLUDE_MATERIAU (Ihm/I_MACRO_ETAPE.py)
modif 2 : modification du parseur python pour amelioration de performance (convert/convert_python.py convert/parseur_python.py)
modif 3 : ne pas afficher des listes trop longues dans l'arbre (Ihm/I_MCSIMP.py, Ihm/I_ASSD.py)

Ihm/I_ASSD.py
Ihm/I_MACRO_ETAPE.py
Ihm/I_MCSIMP.py
convert/convert_python.py
convert/parseur_python.py

index d7ade31b7ee92b139418904c4081dbea0eca13a1..8d30d613515f0cceaacc68aeebeed4b516676e93 100644 (file)
@@ -25,6 +25,10 @@ from Noyau.N_VALIDATOR import ValError
 class ASSD:
    def __repr__(self):
       return "concept %s de type %s" % (self.get_name(),self.__class__.__name__)
+
+   def __str__(self):
+      return self.get_name() or "<None>"
+
    #def __del__(self):
    #   print "__del__",self
 
index 6be22b1242a3b063aedc8d6177f5f126af64a371..258f44ca8e0b7d96917332c34d6a9da29a8220d5 100644 (file)
@@ -59,9 +59,9 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
 
   def get_contexte_jdc(self,fichier,text):
     """ 
-         Interprète text comme un texte de jdc et retourne le 
-         contexte final
-         cad le dictionnaire des sd disponibles à la dernière étape
+         Interprète text comme un texte de jdc et retourne le contexte final.
+
+         Le contexte final est le dictionnaire des sd disponibles à la dernière étape.
          Si text n'est pas un texte de jdc valide, retourne None
          ou leve une exception
          --> utilisée par ops.POURSUITE et INCLUDE
@@ -98,12 +98,14 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
        if fichier is None:fichier="SansNom"
 
        # Il faut convertir le texte inclus en fonction du format
-       format=self.jdc.appli.format_fichier.get()
-       if convert.plugins.has_key(format):
-          # Le convertisseur existe on l'utilise
-          p=convert.plugins[format]()
-          p.text=text
-          text=p.convert('exec',self)
+       # sauf les INCLUDE_MATERIAU
+       if self.nom != "INCLUDE_MATERIAU":
+          format=self.jdc.appli.format_fichier.get()
+          if convert.plugins.has_key(format):
+              # Le convertisseur existe on l'utilise
+              p=convert.plugins[format]()
+              p.text=text
+              text=p.convert('exec',self)
 
        j=self.JdC_aux( procedure=text, nom=fichier,
                                 appli=self.jdc.appli,
@@ -505,8 +507,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
 
   def make_contexte_include(self,fichier,text):
     """
-        Cette méthode sert à créer un contexte en interprétant un texte source
-        Python
+        Cette méthode sert à créer un contexte en interprétant un texte source Python.
     """
     #print "make_contexte_include",fichier
     # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
index 4e84c2a923022477343d5bea2ba4fc3bf50420be..b23639849eea311ba13e895ae79fdb420193eb88 100644 (file)
@@ -76,8 +76,6 @@ class MCSIMP(I_OBJECT.OBJECT):
       return None
     elif type(self.valeur) == types.FloatType : 
       # Traitement d'un flottant isolé
-      # txt = repr_float(self.valeur)
-      # Normalement str fait un travail correct
       txt = str(self.valeur)
       clefobj=self.GetNomConcept()
       if self.jdc.appli.dict_reels.has_key(clefobj):
@@ -86,38 +84,28 @@ class MCSIMP(I_OBJECT.OBJECT):
     elif type(self.valeur) in (types.ListType,types.TupleType) :
       # Traitement des listes
       txt='('
-      i=0
+      sep=''
       for val in self.valeur:
         if type(val) == types.FloatType : 
-           # CCAR : Normalement str fait un travail correct
-           #txt=txt + i*',' + repr_float(val)
            clefobj=self.GetNomConcept()
            if self.jdc.appli.dict_reels.has_key(clefobj):
               if self.jdc.appli.dict_reels[clefobj].has_key(val):
-                 txt=txt + i*',' +self.jdc.appli.dict_reels[clefobj][val]
+                 txt=txt + sep +self.jdc.appli.dict_reels[clefobj][val]
               else :
-                 txt=txt + i*',' + str(val)
+                 txt=txt + sep + str(val)
            else :
-              txt=txt + i*',' + str(val)
-        elif isinstance(val,ASSD): 
-           txt = txt + i*',' + val.get_name()
-    #PN
-    # ajout du elif
-        elif type(val) == types.InstanceType and val.__class__.__name__ in  ('PARAMETRE','PARAMETRE_EVAL'):
-                 txt = txt + i*','+ str(val) 
+              txt=txt + sep + str(val)
         else: 
-           txt = txt + i*','+ myrepr.repr(val)
-        i=1
+           txt = txt + sep+ str(val)
+        if len(txt) > 200:
+            #ligne trop longue, on tronque
+            txt=txt+" ..."
+            break
+        sep=','
       txt=txt+')'
-    elif isinstance(self.valeur,ASSD): 
-      # Cas des ASSD
-      txt=self.getval()
-    elif type(self.valeur) == types.InstanceType and self.valeur.__class__.__name__ in  ('PARAMETRE','PARAMETRE_EVAL'):
-      # Cas des PARAMETRES
-      txt=str(self.valeur)
     else:
       # Traitement des autres cas
-      txt = myrepr.repr(self.valeur)
+      txt = str(self.valeur)
 
     # txt peut etre une longue chaine sur plusieurs lignes.
     # Il est possible de tronquer cette chaine au premier \n et 
index 999dac50291dd84bf325bd5f6777256349e5277b..1c4cc7885e259e9f224405741e7ecbf80167bd68 100644 (file)
@@ -111,10 +111,8 @@ class PythonParser:
             # Erreur lors de la conversion
             l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
                                          sys.exc_info()[2])
-            self.cr.exception("Impossible de convertir le fichier python \
-                               qui doit contenir des erreurs.\n \
-                               On retourne le fichier non converti \n \
-                               Prévenir la maintenance. \n" + string.join(l))
+            self.cr.exception("Impossible de convertir le fichier python qui doit contenir des erreurs.\n"
+                               "On retourne le fichier non converti. Prévenir la maintenance.\n\n" + string.join(l))
             # On retourne néanmoins le source initial non converti (au cas où)
             return self.text
       elif outformat == 'execnoparseur':
index d65dbdfc62dd7c99e980ccb0542f71e7456913aa..d79e8996565fe27444fbc273cc834883df0c28ea 100644 (file)
 import sys,string,re
 import traceback
 
+escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
+stringsAndCommentsRE =  \
+      re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
+allchars = string.maketrans("", "")
+allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
+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
+    """
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        if allstrings[i].startswith("'''")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*##.*")
+#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"[\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)
+
+def construit_genea(texte,liste_mc):
+    """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 liste_mc
+    >>> 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)'
+    >>> construit_genea(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 liste_mc:continue
+            #valeur
+            key=eval(m)
+            if str(key) != m: d[key]=m
+    return d
+
+
 class ENTITE_JDC :
+    """Classe de base pour tous les objets créés lors de la conversion
+       Tout objet dérivé est enregistré auprès de son père à sa création
+    """
     def __init__(self,pere):
         self.texte = ''
         pere.l_objets.append(self)
@@ -35,6 +127,7 @@ class ENTITE_JDC :
         """
         texte = texte+'\n'
         self.texte = self.texte +texte
+
     def __str__(self):
         return self.texte
 
@@ -45,8 +138,11 @@ class COMMENTAIRE(ENTITE_JDC):
         Retourne une chaîne de caractères représentants self
         sous une forme interprétable par EFICAS
         """
-        s='COMMENTAIRE("""'+self.texte+'""")\n\n'
-        return s
+        t=repr(self.texte)
+        return "COMMENTAIRE("+t+")\n"
+
+        #s='COMMENTAIRE("""'+self.texte+'""")\n\n'
+        #return s
 
     def append_text(self,texte):
         """
@@ -92,7 +188,7 @@ class AFFECTATION(ENTITE_JDC):
         """
         if texte[-1] == '\n' : texte = string.rstrip(texte[0:-1])
         if texte[-1] == ';' : texte = string.rstrip(texte[0:-1])
-        self.texte = self.texte+texte
+        self.texte = self.texte+texte+'\n'
         
     def __str__(self):
         """
@@ -100,17 +196,9 @@ class AFFECTATION(ENTITE_JDC):
         et exploitable par EFICAS
         """
         nom,valeur = string.split(self.texte,'=',1)
-      #  print nom,valeur
         n = string.rstrip(nom)
         nom = string.lstrip(n)
         if valeur[-1] == '\n': valeur = valeur[:-1]
-#        valeur = string.strip(valeur)
-        ## traitement des "
-#        if valeur[0]=='"':
-#           valeur=valeur[1:-1]
-#        if valeur[-1]=='"':
-#           valeur=valeur[0:-2]
-
         return n + ' = PARAMETRE(nom=\''+nom+'\',valeur='+valeur+')\n'
 
 class COMMANDE_COMMENTARISEE(ENTITE_JDC):
@@ -231,155 +319,179 @@ class PARSEUR_PYTHON:
         Eclate la chaine self.texte en self.l_objets une liste lignes d'instructions
         et de commentaires (parmi lesquels des instructions "commentarisées").
         """
-        #AY##l_lignes = open(self.fichier,'r').readlines()
         l_lignes = string.split(self.texte,'\n')
         commentaire_courant             = None
         commande_courante               = None
         affectation_courante            = None
         commande_commentarisee_courante = None
         self.l_objets = []
-        # PN pour corriger le pb des fins de ligne commentes
-        # par exemple P=1 # profondeur
-        liste=[]
-        for ligne in l_lignes :
-          if ligne.find("#") > 2 :
-            l1,l2=ligne.split("#",1)
-            queBlanc=1
-            i=0
-            while ( i < len(l1)) :
-                if l1[i] != " " : 
-                   queBlanc = 0
-                    break
-                i=i+1 
-            if queBlanc :
-                liste.append(ligne)
-            else :
-               # Il faut vérifier que le commentaire n 'est pas dans une chaine
-                ind1=ligne.find("'")
-                ind2=ligne.find("'",ind1+1)
-                if ind1 < ligne.find("#") < ind2 :
-                  liste.append(ligne)
-                else:
-                   l1=l1+"\n"
-                   liste.append(l1)
-                   l2="#"+l2
-                   liste.append(l2)
-          else :
-            liste.append(ligne)
-        # PN fin des commentaires
 
-        l_lignes=liste
-        cpt = 0
+        #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))
+        #print srcMasked
+        masked_lines=srcMasked.split('\n')
+        lineno=0
+
         for ligne in l_lignes :
-            cpt = cpt+1
+            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("'''") % 2
+            #print hangingComments,hangingBraces
+            if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0: 
+                raise ParserException()
+
             if string.strip(ligne) == '':
                 # il s'agit d'un saut de ligne
                 # --> on l'ignore
                 continue
-            else:
-                liste = string.split(ligne,'##',1)
-                if len(liste) > 1:
-                    # on a trouvé un double commentaire dans la ligne
-                    before,after = liste
-                    if string.strip(before) == '':
-                        # il s'agit d'une commande commentarisée
-                        if commentaire_courant :
-                            commentaire_courant = None
-                        elif commande_courante :
-                            # on a un objet commentarisé à l'intérieur d'une commande
-                            # --> non traité pour l'instant
-                            commande_courante.append_text(ligne)
-                        elif commande_commentarisee_courante :
-                            # commande_commentarisee en cours : on ajoute la ligne
-                            commande_commentarisee_courante.append_text(ligne)
-                        else:
-                            # on crée un objet commande_commentarisee_courante
-                            commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
-                            commande_commentarisee_courante.append_text(ligne)
-                        # si la ligne courante se termine par un ';', on décide - par hypothèse et peut-être à tort - que
-                        # la commande commentarisée courante est terminée !!
-                        if re.search( '; *$', ligne ) != None :
-                            commande_commentarisee_courante = None
-                        continue
-                    else:
-                        # on a un double commentaire en fin de ligne
-                        # --> pour l'instant on ne fait rien
-                        pass
-                new_ligne = string.split(ligne,'#')[0] # on enlève toute la partie commentaire de la ligne
-                new_ligne = string.strip(new_ligne)
-                if new_ligne == '' :
-                    # la ligne n'est qu'un commentaire précédé d'éventuels blancs
-                    if commande_courante :
-                        # il s'agit d'un commentaire à l'intérieur d'une commande --> on ne fait rien
-                        commande_courante.append_text(ligne)
-                    elif commentaire_courant :
-                        # il s'agit de la nième ligne d'un commentaire entre deux commandes
-                        # --> on ajoute cette ligne au commentaire courant
-                        #print "ici1",ligne
-                        commentaire_courant.append_text(ligne)
-                    else :
-                        # il s'agit d'un commentaire entre deux commandes
-                        # --> on le crée et il devient le commentaire courant
-                        commentaire_courant = COMMENTAIRE(self)
-                        #print "ici2",ligne
-                        commentaire_courant.append_text(ligne)
+
+            if pattern_2comments.match(ligne):
+                #on a trouvé une commande commentarisée : double commentaire sans rien devant à 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 commentarisé à l'intérieur d'une commande
+                    # --> non traité pour l'instant : on l'ajoute simplement a la commande courante comme
+                    # un commentaire ordinaire
+                    commande_courante.append_text(ligne)
+                elif commande_commentarisee_courante :
+                    # commande_commentarisee en cours : on ajoute la ligne
+                    commande_commentarisee_courante.append_text(ligne)
                 else:
-                    # la ligne contient des données autre qu'un éventuel commentaire
-                    if commentaire_courant :
-                        # on clôt un éventuel commentaire courant
-                        commentaire_courant = None
-                    if commande_courante :
-                        commande_courante.append_text(ligne)
-                        if commande_courante.get_nb_par() == 0:
-                            # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
-                            try :
-                               self.analyse_reel(commande_courante.texte)
-                            except :
-                               pass
-                            commande_courante = None
+                    # debut de commande commentarisée : on crée un objet commande_commentarisee_courante
+                    commande_commentarisee_courante = COMMANDE_COMMENTARISEE(self)
+                    commande_commentarisee_courante.append_text(ligne)
+
+                #on passe à 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 à l'intérieur d'une commande --> on ne fait rien de special
+                    #on l'ajoute au texte de la commande 
+                    commande_courante.append_text(ligne)
+                elif commentaire_courant :
+                    # il s'agit de la nième ligne d'un commentaire entre deux commandes
+                    # --> on ajoute cette ligne au commentaire courant
+                    commentaire_courant.append_text(ligne)
+                else :
+                    # il s'agit d'un nouveau commentaire entre deux commandes
+                    # --> on le crée et il devient le commentaire courant
+                    commentaire_courant = COMMENTAIRE(self)
+                    commentaire_courant.append_text(ligne)
+
+                #on passe à la ligne suivante
+                continue
+
+            # la ligne contient des données autre qu'un éventuel commentaire
+            if commentaire_courant :
+                # on clôt un éventuel commentaire courant
+                commentaire_courant = None
+
+            if commande_commentarisee_courante :
+                # on clôt une éventuelle 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.append_text(ligne)
+                if not linecontinueRE.search(line) and (hangingBraces == emptyHangingBraces) and not hangingComments:
+                    #la commande est terminée 
+                    #print "fin de commande"
+                    self.analyse_reel(commande_courante.texte)
+                    commande_courante = None
+
+                #on passe à la ligne suivante
+                continue
+
+            if affectation_courante != None :
+                #poursuite d'une affectation
+                affectation_courante.append_text(ligne)
+                if not linecontinueRE.search(line) and (hangingBraces == emptyHangingBraces) and not hangingComments:
+                    #L'affectation est terminée
+                    affectation_courante=None
+                #on passe à la ligne suivante
+                continue
+
+            # il peut s'agir d'une commande ou d'une affectation ...
+            # ou d'un EVAL !!!
+            if self.is_eval(ligne):
+                # --> affectation de type EVAL
+                if affectation_courante : affectation_courante = None
+                affectation = AFFECTATION_EVAL(self)
+                affectation.append_text(ligne)
+                #on passe à la ligne suivante
+                continue
+
+            if self.is_affectation(ligne):
+                # --> affectation
+                text=ligne
+                #traitement des commentaires en fin de ligne
+                compos=line.find("#")
+                if compos > 2:
+                    #commentaire en fin de ligne
+                    #on cree un nouveau commentaire avant le parametre
+                    COMMENTAIRE(self).append_text(ligne[compos:])
+                    text=ligne[:compos]
+                #si plusieurs instructions separees par des ; sur la meme ligne
+                inspos=line.find(";")
+                if inspos > 2:
+                    #on garde seulement la premiere partie de la ligne
+                    #si on a que des blancs apres le point virgule
+                    if string.strip(text[inspos:]) == ";":
+                        text=text[:inspos]
                     else:
-                        # il peut s'agir d'une commande ou d'une affectation ...
-                        # ou de la poursuite d'une affectation !!!!!
-                        # ou d'un EVAL !!!
-                        if self.is_eval(new_ligne):
-                            # --> affectation de type EVAL
-                            if affectation_courante : affectation_courante = None
-                            affectation = AFFECTATION_EVAL(self)
-                            affectation.append_text(ligne)
-                        elif self.is_affectation(new_ligne):
-                            # --> affectation
-                            affectation_courante = AFFECTATION(self)
-                            affectation_courante.append_text(ligne)
-                        elif self.is_commande(new_ligne):
-                            # --> commande
-                            commande_courante = COMMANDE(self)
-                            commande_courante.append_text(ligne)
-                            affectation_courante = None
-                            if commande_courante.get_nb_par() == 0:
-                                # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
-                                self.analyse_reel(commande_courante.texte)
-                                commande_courante = None
-                        else:
-                            if commande_courante:
-                               # commande en cours
-                               commande_courante.append_text(ligne)
-                               affectation_courante = None
-                               if commande_courante.get_nb_par() == 0:
-                                  # la commande courante est terminée (autant de parenthèses fermantes qu'ouvrantes)
-                                  self.analyse_reel(commande_courante.texte)
-                                  commande_courante = None
-                            else:
-                              #print 'ici3',ligne
-                              #e=ENTITE_JDC(self)
-                              #e.append_text(ligne)
-                              #--> poursuite d'une affectation
-                              # PN -- pour Empecher une erreur pas propre
-                              if affectation_courante != None :
-                                 affectation_courante.append_text(ligne)
-                              #affectation_courante.append_text(ligne)
+                        raise FatalError("Eficas ne peut pas traiter plusieurs instructions sur la meme ligne : %s" % ligne)
+
+                affectation_courante = AFFECTATION(self)
+                affectation_courante.append_text(text)
+                if not linecontinueRE.search(line) and (hangingBraces == emptyHangingBraces) and not hangingComments:
+                    #L'affectation est terminée
+                    affectation_courante=None
+                #on passe à la ligne suivante
+                continue
 
+            if self.is_commande(ligne):
+                # --> nouvelle commande
+                affectation_courante = None
+                commande_courante = COMMANDE(self)
+                commande_courante.append_text(ligne)
+                #si la commande est complète, on la termine
+                if not linecontinueRE.search(line) and (hangingBraces == emptyHangingBraces) and not hangingComments:
+                    #la commande est terminée 
+                    #print "fin de commande"
+                    self.analyse_reel(commande_courante.texte)
+                    commande_courante = None
+                #on passe à la ligne suivante
+                continue
 
     def enleve (self,texte) :
+        """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations
+           Le nouveau texte est retourné
+        """
         i=0
         chaine=""
         while (i<len(texte)):
@@ -401,9 +513,11 @@ class PARSEUR_PYTHON:
            if ( c == "," or c == "(" or c == ")"):
               mot=""
            elif ( c== "="):
+              #on doit trouver derriere soit une valeur soit une parenthese
               valeur=""
               nouvelindice=indiceC+1
               if texte[nouvelindice] != "(":
+                 #pas de parenthese ouvrante derriere un signe =, on a une valeur.
                  while ( texte[nouvelindice] != "," and texte[nouvelindice] != ")"):
                     valeur=valeur+texte[nouvelindice]
                     nouvelindice=nouvelindice+1
@@ -421,9 +535,13 @@ class PARSEUR_PYTHON:
                  mot=""
                  indiceC=nouvelindice
               else:
-               # s agit -il d un tuple 
+                 #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] != "(":
+                    #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
@@ -434,6 +552,7 @@ class PARSEUR_PYTHON:
                              nouvelindice=nouvelindice -1
                              break
                     if tuple :
+                       #cas du tuple de valeurs
                        valeur=texte[indiceC+1:nouvelindice+1]
                        indiceC=nouvelindice+1 
                        if mot in self.appli.liste_simp_reel:
@@ -450,6 +569,7 @@ class PARSEUR_PYTHON:
                        mot=""
                # ou de ( imbriqueés
                  else :
+                    #cas du mocle facteur simple ou 
                     mot=""
            else :
               mot=mot+texte[indiceC]
@@ -465,11 +585,15 @@ class PARSEUR_PYTHON:
         if commande.find("=") > commande.find("(") :
            return
         if commande.find("=") > 0:
-           epure1=self.enleve(commande)
-           nomConcept=epure1.split("=")[0]
-           index=epure1.find("=")
-           epure2=epure1[index+1:len(epure1)].replace("_F(","(")
-           dict_reel_concept=self.construit_genea(epure2)
+           #epure1=self.enleve(commande)
+           epure1=pattern_blancs.sub("",commande)
+           nomConcept,corps=epure1.split("=",1)
+           epure2=corps.replace("_F(","(")
+           #nomConcept=epure1.split("=")[0]
+           #index=epure1.find("=")
+           #epure2=epure1[index+1:len(epure1)].replace("_F(","(")
+           #dict_reel_concept=self.construit_genea(epure2)
+           dict_reel_concept=construit_genea(epure2,self.appli.liste_simp_reel)
         if nomConcept !=None :
            if len(dict_reel_concept) != 0:
               self.appli.dict_reels[nomConcept]=dict_reel_concept
@@ -479,22 +603,43 @@ class PARSEUR_PYTHON:
         Retourne le texte issu de l'analyse
         """
         self.appli=appli
-        if not self.l_objets : self.analyse()
-        txt=''
-        for obj in self.l_objets:
-            txt = txt+str(obj)
+        try:
+            if not self.l_objets : self.analyse()
+            txt=''
+            for obj in self.l_objets:
+                txt = txt+str(obj)
+        except ParserException:
+            #Impossible de convertir le texte, on le retourne tel que
+            txt=self.texte
         return txt
 
 if __name__ == "__main__" :
+    import time
     #fichier = 'D:/Eficas_dev/Tests/zzzz100a.comm'
     fichier = 'U:/Eficas_dev/Tests/test_eval.comm'
     fichier = '/local/chris/ASTER/Eficas/Eficas1_10/EficasV1/Tests/testcomm/b.comm'
-    fichier = '/local/chris/ASTER/instals/STA8.2/astest/forma11d.comm'
+    fichier = '/local/chris/ASTER/instals/STA8.2/astest/forma12c.comm'
+    fichier = 'titi.comm'
     texte = open(fichier,'r').read()
     class appli:
        dict_reels={}
-       liste_simp_reel=[]
-    txt = PARSEUR_PYTHON(texte).get_texte(appli())
+       liste_simp_reel=["VALE","VALE_C","GROUP_MA","RAYON"]
+    a=appli()
+
+    if 1:
+        t0=time.clock()
+        txt = PARSEUR_PYTHON(texte).get_texte(a)
+        print t0,time.clock()-t0
+    else:
+        import hotshot, hotshot.stats
+        prof = hotshot.Profile("stones.prof")
+        txt = prof.runcall(PARSEUR_PYTHON(texte).get_texte,a)
+        prof.close()
+        stats = hotshot.stats.load("stones.prof")
+        stats.strip_dirs()
+        stats.sort_stats('time', 'calls')
+        stats.print_stats(20)
+
     print txt
     compile(txt, '<string>', 'exec')
-    
+    print a.dict_reels