X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=convert%2Fparseur_python.py;h=19d73256de77e60caf79b1e4929d2c6745ff8044;hb=0a3e507740b8094749648d8292fa83b10e2ea864;hp=cd52202832bbcbca14d51c9df874e3d2555fe551;hpb=277e53856e5b826d6d495db3ff575118547cb9d4;p=tools%2Feficas.git diff --git a/convert/parseur_python.py b/convert/parseur_python.py index cd522028..19d73256 100644 --- a/convert/parseur_python.py +++ b/convert/parseur_python.py @@ -1,62 +1,198 @@ # -*- coding: utf-8 -*- -# CONFIGURATION MANAGEMENT OF EDF VERSION -# ====================================================================== -# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG -# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY -# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY -# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR -# (AT YOUR OPTION) ANY LATER VERSION. +# Copyright (C) 2007-2021 EDF R&D # -# THIS PROGRAM 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 -# GENERAL PUBLIC LICENSE FOR MORE DETAILS. +# 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. # -# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE -# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# 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 -class ENTITE_JDC : +#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 set_text(self,texte): + def setText(self,texte): self.texte = texte - def append_text(self,texte): + def appendText(self,texte): """ - Ajoute texte à self.texte en mettant un retour chariot à la fin de 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 chaîne de caractères représentants self - sous une forme interprétable par EFICAS + Retourne une chaine de caracteres representants self + sous une forme interpretable par EFICAS """ - s='COMMENTAIRE("""'+self.texte+'""")\n\n' - return s + t=repr(self.texte) + return "COMMENTAIRE(u"+t+")\n" + + #s='COMMENTAIRE(u"""'+self.texte+'""")\n\n' + #return s - def append_text(self,texte): + def appendText(self,texte): """ - Ajoute texte à self.texte en enlevant le # initial + Ajoute texte a self.texte en enlevant le # initial """ texte = texte+'\n' if texte[0] == '#': self.texte = self.texte+texte[1:] else: - # le dièse n'est pas sur le premier caractère - amont,aval = string.split(texte,'#',1) # on découpe suivant la première occurrence de # + # 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): @@ -64,373 +200,497 @@ class COMMANDE(ENTITE_JDC): Retourne self.texte """ return self.texte+'\n' - - def get_nb_par(self): + + def getNbPar(self): """ - Retourne la différence entre le nombre de parenthèses ouvrantes - et le nombre de parenthèses fermantes présentes dans self.texte - Peut donc retourner un entier négatif + 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-mêmes contenir des parenthèses !!!! - l_lignes = string.split(self.texte,'\n') + # qui peuvent eux-memes contenir des parentheses !!!! + l_lignes = self.texte.split('\n') nb = 0 for ligne in l_lignes: - ligne = string.split(ligne,'#')[0] - nb = nb + (string.count(ligne,'(')-string.count(ligne,')')) + 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 append_text(self,texte): + def appendText(self,texte): """ - Ajoute texte à self.texte en enlevant tout retour chariot et tout point virgule + Ajoute texte a self.texte en enlevant tout retour chariot et tout point virgule + PN et tout commentaire """ - if texte[-1] == '\n' : texte = string.strip(texte[0:-1]) - if texte[-1] == ';' : texte = string.strip(texte[0:-1]) - self.texte = self.texte+texte - + 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 compréhensible par ACCAS + Retourne une expression de l'affectation comprehensible par ACCAS et exploitable par EFICAS """ - nom,valeur = string.split(self.texte,'=',1) - nom = string.strip(nom) + nom,valeur = self.texte.split('=',1) + n = nom.rstrip() + nom = n.lstrip() 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 nom+' = PARAMETRE(nom=\''+nom+'\',valeur="'+valeur+'")\n\n' + return n + ' = PARAMETRE(nom=\''+nom+'\',valeur='+valeur+')\n' class COMMANDE_COMMENTARISEE(ENTITE_JDC): - def append_text(self,texte): + def appendText(self,texte): """ - Ajoute texte à self.texte en enlevant les doubles commentaires + Ajoute texte a self.texte en enlevant les doubles commentaires """ - texte = string.strip(texte) - texte = string.strip(texte[2:]) + 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 commentarisée compréhensible par ACCAS + Retourne une expression de la commande commentarisee comprehensible par ACCAS et exploitable par EFICAS """ - return "COMMANDE_COMM(texte='''"+self.texte+"''')\n" + return "COMMANDE_COMM(texte="+repr(self.texte)+")\n" + #return "COMMANDE_COMM(texte='''"+self.texte+"''')\n" class AFFECTATION_EVAL(ENTITE_JDC): - def append_text(self,texte): + def appendText(self,texte): """ - Ajoute texte à self.texte en enlevant tout retour chariot + 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 paramètre EVAL compréhensible par ACCAS + Retourne une expression du parametre EVAL comprehensible par ACCAS et exploitable par EFICAS """ - nom,valeur = string.split(self.texte,'=',1) - nom = string.strip(nom) + nom,valeur = self.texte.split('=',1) + nom = nom.strip() if valeur[-1] == '\n': valeur = valeur[:-1] - valeur = string.strip(valeur) + valeur = valeur.strip() return nom+' = PARAMETRE_EVAL(nom=\''+nom+'\',valeur=\''+valeur+'\')\n\n' - -class PARSEUR_PYTHON: + +class PARSEUR_PYTHON(object): """ - Cette classe sert à générer un objet PARSEUR_PYTHON qui réalise l'analyse d'un texte - représentant un JDC Python en distinguant : + 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-Z0-9_]+)([ \t\r\f\v]*)\(([\w\W]*)') + 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.appli=None + self.appliEficas=None - def is_affectation(self,texte): + def isAffectation(self,texte): """ - Méthode booléenne qui retourne 1 si le texte est celui d'une affectation dans un jeu de commandes + 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 procédure ... + # cas d'une procedure ... return 0 - amont,aval = string.split(texte,'=',1) - aval = string.strip(aval) + 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 is_eval(self,texte): + def isEval(self,texte): """ - Méthode booléenne qui retourne 1 si le texte est celui d'une affectation de type EVAL + 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 procédure ... + # cas d'une procedure ... return 0 - amont,aval = string.split(texte,'=',1) - aval = string.strip(aval) + 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 is_commande(self,texte): + + def isCommande(self,texte): """ - Méthode booléenne qui retourne 1 si le texte est celui d'une commande dans un jeu de commandes + 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 procédure ... + # 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 à analyser yyyy - amont,aval = string.split(texte,'=',1) - aval = string.strip(aval) + # --> 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 "commentarisées"). + et de commentaires (parmi lesquels des instructions "commentarisees"). """ - #AY##l_lignes = open(self.fichier,'r').readlines() - l_lignes = string.split(self.texte,'\n') + l_lignes = self.texte.split('\n') commentaire_courant = None commande_courante = None affectation_courante = None commande_commentarisee_courante = None self.l_objets = [] - 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)) + masked_lines=srcMasked.split('\n') + lineno=0 + for ligne in l_lignes : - cpt = cpt+1 - if string.strip(ligne) == '': + 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 - 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 - 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) - commentaire_courant.append_text(ligne) + + 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: - # 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 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: - # 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: - #--> 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(tr("Eficas ne peut pas traiter plusieurs instructions \ + sur la meme ligne : %s", ligne)) + + affectation_courante = AFFECTATION(self) + affectation_courante.appendText(text) + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #L'affectation est terminee + affectation_courante=None + #on passe a la ligne suivante + continue + + if self.isCommande(ligne): + # --> nouvelle commande + affectation_courante = None + commande_courante = COMMANDE(self) + commande_courante.appendText(ligne) + #si la commande est complete, on la termine + if not linecontinueRE.search(line) \ + and (hangingBraces == emptyHangingBraces) \ + and not hangingComments: + #la commande est terminee + self.analyseReel(commande_courante.texte) + commande_courante = None + #on passe a la ligne suivante + continue def enleve (self,texte) : + """Supprime de texte tous les caracteres blancs, fins de ligne, tabulations + Le nouveau texte est retourne + """ i=0 chaine="" while (i', 'exec') + print((a.dict_reels))