]> SALOME platform Git repositories - modules/eficas.git/commitdiff
Salome HOME
ajout traducteur syntaxique
authorChristian Caremoli <>
Mon, 24 Apr 2006 12:51:42 +0000 (12:51 +0000)
committerChristian Caremoli <>
Mon, 24 Apr 2006 12:51:42 +0000 (12:51 +0000)
Traducteur/jdcparser.py [new file with mode: 0644]
Traducteur/load.py [new file with mode: 0644]
Traducteur/log.py [new file with mode: 0644]
Traducteur/mocles.py [new file with mode: 0644]
Traducteur/parseur.py [new file with mode: 0644]
Traducteur/removemocle.py [new file with mode: 0644]
Traducteur/renamemocle.py [new file with mode: 0644]
Traducteur/toto.comm [new file with mode: 0644]
Traducteur/utils.py [new file with mode: 0644]
Traducteur/visiteur.py [new file with mode: 0644]

diff --git a/Traducteur/jdcparser.py b/Traducteur/jdcparser.py
new file mode 100644 (file)
index 0000000..8e450b6
--- /dev/null
@@ -0,0 +1,34 @@
+import log
+
+from load import getJDC
+from mocles import parseKeywords
+import removemocle
+import renamemocle
+
+atraiter=("DEBUT","LIRE_MAILLAGE","AFFE_MODELE","DEFI_GROUP",
+          "AFFE_MATERIAU","DEFI_MATERIAU","STAT_NONLINE",
+         )
+
+filename="toto.comm"
+jdc=getJDC(filename,atraiter)
+root=jdc.root
+
+#Parse les mocles des commandes
+parseKeywords(root)
+
+removemocle.removemocleinfact(jdc,"AFFE_MATERIAU","AFFE","TOUT")
+removemocle.removemocle(jdc,"STAT_NONLINE","SOLVEUR")
+renamemocle.renamemocleinfact(jdc,"AFFE_MODELE","AFFE","PHENOMENE","TOTO")
+renamemocle.renamemocleinfact(jdc,"AFFE_MODELE","AFFE","MODELISATION","TITI")
+renamemocle.renamemocleinfact(jdc,"DEFI_GROUP","CREA_GROUP_NO","GROUP_MA","TUTU")
+removemocle.removemocle(jdc,"LIRE_MAILLAGE","INFO")
+removemocle.removemocle(jdc,"LIRE_MAILLAGE","UNITE")
+renamemocle.renamemocle(jdc,"DEFI_MATERIAU","ELAS","ELASTIC")
+renamemocle.renamemocle(jdc,"AFFE_MATERIAU","MAILLAGE","MAILL")
+removemocle.removemocleinfact(jdc,"STAT_NONLINE","SOLV","METHOD")
+removemocle.removemocle(jdc,"STAT_NONLINE","AFFE")
+
+
+f=open("tutu.comm",'w')
+f.write(jdc.getSource())
+f.close()
diff --git a/Traducteur/load.py b/Traducteur/load.py
new file mode 100644 (file)
index 0000000..90757c0
--- /dev/null
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+import os
+import parseur
+from mocles import parseKeywords
+
+atraiter=("DEBUT","LIRE_MAILLAGE","AFFE_MODELE","DEFI_GROUP",
+                  "AFFE_MATERIAU","DEFI_MATERIAU",
+                      )
+
+JDCdict={}
+
+class JDC:
+    """Cet objet conserve toutes les informations relatives à un fichier de commandes .comm"""
+    def __init__(self,filename,src,atraiter):
+        self.filename = os.path.abspath(filename)
+        self.atraiter=atraiter
+        self.init(src,atraiter)
+
+    def init(self,src,atraiter):
+        self.root=parseur.parser(src,atraiter)
+        self.lines=src.splitlines(1)
+
+    def parseKeywords(self):
+        parseKeywords(self.root)
+
+    def reset(self,src):
+        self.init(src,self.atraiter)
+        self.parseKeywords()
+
+    def getSource(self):
+        return  "".join(self.getLines())
+
+    def getLine(self,linenum):
+        return self.getLines()[linenum-1]
+
+    def getLines(self):
+        return self.lines
+
+def getJDC(filename,atraiter=atraiter):
+    jdc=JDCdict.get(filename)
+    if not jdc: 
+        f=open(filename)
+        src=f.read()
+        f.close()
+        jdc=JDC(filename,src,atraiter)
+        JDCdict[filename]=jdc
+    return jdc
+
diff --git a/Traducteur/log.py b/Traducteur/log.py
new file mode 100644 (file)
index 0000000..0499433
--- /dev/null
@@ -0,0 +1,8 @@
+import logging
+logger=logging.getLogger()
+hdlr=logging.FileHandler('convert.log','w')
+#formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+formatter = logging.Formatter('%(levelname)s: %(message)s')
+hdlr.setFormatter(formatter)
+logger.addHandler(hdlr) 
+logger.setLevel(logging.INFO)
diff --git a/Traducteur/mocles.py b/Traducteur/mocles.py
new file mode 100644 (file)
index 0000000..f9429ad
--- /dev/null
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+
+import compiler
+import types
+from parseur import Keyword,FactNode,lastparen,lastparen2
+from visiteur import KeywordFinder,visitor
+from utils import indexToCoordinates
+
+debug=0
+
+def parseFact(match,c,kw):
+    submatch=match[2]
+    lastpar=match[0]+lastparen(c.src[match[0]:])
+    if type(submatch[0][0]) ==types.IntType:
+        #mot cle facteur isolé
+        no=FactNode()
+        kw.addChild(no)
+        for ii in range(len(submatch)-1):
+            e=submatch[ii]
+            x,y=indexToCoordinates(c.src,e[0])
+            lineno=y+c.lineno
+            colno=x
+            x,y=indexToCoordinates(c.src,submatch[ii+1][0])
+            endline=y+c.lineno
+            endcol=x
+            no.addChild(Keyword(e[1],lineno,colno,endline,endcol))
+        #last one
+        e=submatch[-1]
+        x,y=indexToCoordinates(c.src,e[0])
+        lineno=y+c.lineno
+        colno=x
+        x,y=indexToCoordinates(c.src,lastpar-1)
+        endline=y+c.lineno
+        endcol=x
+        no.addChild(Keyword(e[1],lineno,colno,endline,endcol))
+    else:
+        #mot cle facteur multiple
+        ii=0
+        for l in submatch:
+            lastpar=l[0][0]+lastparen2(c.src[l[0][0]:])
+            ii=ii+1
+            no=FactNode()
+            kw.addChild(no)
+            for j in range(len(l)-1):
+                e=l[j]
+                x,y=indexToCoordinates(c.src,e[0])
+                lineno=y+c.lineno
+                colno=x
+                x,y=indexToCoordinates(c.src,l[j+1][0])
+                endline=y+c.lineno
+                endcol=x
+                no.addChild(Keyword(e[1],lineno,colno,endline,endcol))
+            #last one
+            e=l[-1]
+            x,y=indexToCoordinates(c.src,e[0])
+            lineno=y+c.lineno
+            colno=x
+            x,y=indexToCoordinates(c.src,lastpar-1)
+            endline=y+c.lineno
+            endcol=x
+            no.addChild(Keyword(e[1],lineno,colno,endline,endcol))
+
+
+def parseKeywords(root):
+    """A partir d'un arbre contenant des commandes, ajoute les noeuds fils correspondant aux mocles
+       de la commande
+    """
+    matchFinder=KeywordFinder()
+
+    for c in root.childNodes:
+        ast=compiler.parse(c.src)
+        #print ast
+        matchFinder.reset(c.src)
+        visitor.walk(ast, matchFinder)
+        #print matchFinder.matches
+        if len(matchFinder.matches) > 1:
+            #plusieurs mocles trouvés : un mocle commence au début du keyword (matchFinder.matches[i][0])
+            # et finit juste avant le keyword suivant (matchFinder.matches[i+1][0]])
+            for i in range(len(matchFinder.matches)-1):
+                if debug:print "texte:",c.src[matchFinder.matches[i][0]:matchFinder.matches[i+1][0]]
+                x,y=indexToCoordinates(c.src,matchFinder.matches[i][0])
+                lineno=y+c.lineno
+                colno=x
+                x,y=indexToCoordinates(c.src,matchFinder.matches[i+1][0])
+                endline=y+c.lineno
+                endcol=x
+                if debug:print matchFinder.matches[i][0],matchFinder.matches[i][1],lineno,colno,endline,endcol
+                kw=Keyword(matchFinder.matches[i][1],lineno,colno,endline,endcol)
+                c.addChild(kw)
+                submatch= matchFinder.matches[i][2]
+                if submatch:
+                    parseFact(matchFinder.matches[i],c,kw)
+            #dernier mocle : il commence au debut du dernier keyword (matchFinder.matches[i+1][0]) et
+            #finit avant la parenthese fermante de la commande (c.lastparen)
+            if debug:print "texte:",c.src[matchFinder.matches[i+1][0]:c.lastparen]
+            x,y=indexToCoordinates(c.src,matchFinder.matches[i+1][0])
+            lineno=y+c.lineno
+            colno=x
+            x,y=indexToCoordinates(c.src,c.lastparen)
+            endline=y+c.lineno
+            endcol=x
+            if debug:print matchFinder.matches[i+1][0],matchFinder.matches[i+1][1],lineno,colno,endline,endcol
+            kw=Keyword(matchFinder.matches[i+1][1],lineno,colno,endline,endcol)
+            c.addChild(kw)
+            submatch= matchFinder.matches[i+1][2]
+            if submatch:
+                parseFact(matchFinder.matches[i+1],c,kw)
+
+        elif len(matchFinder.matches) == 1:
+            #un seul mocle trouve : il commence au début du keyword (matchFinder.matches[0][0]) et 
+            #finit juste avant la parenthese fermante de la commande (c.lastparen)
+            if debug:print "texte:",c.src[matchFinder.matches[0][0]:c.lastparen]
+            x,y=indexToCoordinates(c.src,matchFinder.matches[0][0])
+            lineno=y+c.lineno
+            colno=x
+            x,y=indexToCoordinates(c.src,c.lastparen)
+            endline=y+c.lineno
+            endcol=x
+            if debug:print matchFinder.matches[0][0],matchFinder.matches[0][1],lineno,colno,endline,endcol
+            kw=Keyword(matchFinder.matches[0][1],lineno,colno,endline,endcol)
+            c.addChild(kw)
+            submatch= matchFinder.matches[0][2]
+            if submatch:
+                parseFact(matchFinder.matches[0],c,kw)
+        else:
+            pass
+
diff --git a/Traducteur/parseur.py b/Traducteur/parseur.py
new file mode 100644 (file)
index 0000000..54f5861
--- /dev/null
@@ -0,0 +1,199 @@
+# -*- coding: utf-8 -*-
+import re,string
+import compiler
+
+debug=0
+
+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):
+    """Remplace tous les caracteres dans commentaires et strings par des * """
+    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)
+
+#un nombre queconque de blancs,un nom,des blancs
+pattern_oper   = re.compile(r"^\s*(.*?=\s*)?([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
+pattern_proc   = re.compile(r"^\s*([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
+
+implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
+linecontinueRE = re.compile(r"\\\s*(#.*)?$")
+emptyHangingBraces = [0,0,0,0,0]
+
+class UnbalancedBracesException: pass
+
+class Node:
+    def __init__(self):
+        self.childNodes=[]
+
+    def addChild(self,node):
+        self.childNodes.append(node)
+
+class FactNode(Node):pass
+class JDCNode(Node):
+    def __init__(self,src):
+        Node.__init__(self)
+        self.src=src
+
+class Command(Node):
+    def __init__(self,name,lineno,colno,firstparen):
+        Node.__init__(self)
+        self.name=name
+        self.lineno=lineno
+        self.colno=colno
+        self.firstparen=firstparen
+
+class Keyword(Node):
+    def __init__(self,name,lineno,colno,endline,endcol):
+        Node.__init__(self)
+        self.name=name
+        self.lineno=lineno
+        self.colno=colno
+        self.endline=endline
+        self.endcol=endcol
+
+def printNode(node):
+    if hasattr(node,'name'):
+        print node.name
+    else:
+        print "pas de nom pour:",node
+    for c in node.childNodes:
+        printNode(c)
+
+def parser(src,atraiter):
+    """Parse le texte src et retourne un arbre syntaxique (root).
+
+       Cet arbre syntaxique a comme noeuds (childNodes) les commandes à traiter (liste atraiter)
+    """
+    lines=src.splitlines(1)
+    maskedSrc=maskStringsAndComments(src)
+    #print maskedSrc
+    maskedLines=maskedSrc.splitlines(1)
+
+    root=JDCNode(src)
+
+    # (a) dans un premier temps on extrait les commandes et on les insère dans un arbre (root) 
+    # les noeuds fils sont stockés dans root.childNodes (liste)
+    lineno=0
+    for line in maskedLines:
+        lineno=lineno+1
+        if debug:print "line",lineno,":",line
+        m=pattern_proc.match(line)
+        if m and (m.group(1) in atraiter):
+            if debug:print m.start(3),m.end(3),m.start(4)
+            root.addChild(Command(m.group(1),lineno,m.start(1),m.end(3)))
+        else:
+            m=pattern_oper.match(line)
+            if m and (m.group(2) in atraiter):
+                root.addChild(Command(m.group(2),lineno,m.start(2),m.end(4)))
+
+    #(b) dans un deuxième temps , on récupère le texte complet de la commande jusqu'à la
+    # dernière parenthèse fermante
+
+    #iterateur sur les lignes physiques masquées
+    iterlines=iter(maskedLines)
+
+    linenum=0
+    for c in root.childNodes:
+        lineno=c.lineno
+        colno=c.colno # début de la commande
+        while linenum < lineno:
+            line=iterlines.next()
+            linenum=linenum+1
+            if linenum != lineno:
+                if debug:print "line %s:"%linenum, line
+        tmp = []
+        hangingBraces = list(emptyHangingBraces)
+        hangingComments = 0
+        while 1:
+            # update hanging braces
+            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
+    
+            if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0:
+                raise UnbalancedBracesException()
+
+            if linecontinueRE.search(line):
+                tmp.append(lines[linenum-1])
+            elif hangingBraces != emptyHangingBraces:
+                tmp.append(lines[linenum-1])
+            elif hangingComments:
+                tmp.append(lines[linenum-1])
+            else:
+                tmp.append(lines[linenum-1])
+                src="".join(tmp)
+                c.src=src
+                c.endline=linenum
+                decal=len(line)-line.rindex(')')
+                c.lastparen=len(src)-decal
+                if debug:print "logical line %s %s:" % (c.lineno,c.endline),src
+                break
+            line=iterlines.next()
+            linenum=linenum+1
+
+    return root
+
+
+def lastparen(src):
+    """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
+
+       La string doit contenir la premiere parenthese ouvrante
+    """
+    src=maskStringsAndComments(src)
+    level=0
+    i,n=0,len(src)
+    while i < n:
+        ch=src[i]
+        i=i+1
+        if ch in ('(','['):
+            level=level+1
+        if ch in (')',']'):
+            if level == 0:
+                raise UnbalancedBracesException()
+            level=level-1
+            if level == 0:
+                #derniere parenthese fermante
+                return i
+
+def lastparen2(src):
+    """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
+
+       La string ne contient pas la premiere parenthese ouvrante
+    """
+    src=maskStringsAndComments(src)
+    level=1
+    i,n=0,len(src)
+    while i < n:
+        ch=src[i]
+        i=i+1
+        if ch in ('(','['):
+            level=level+1
+        if ch in (')',']'):
+            if level == 0:
+                raise UnbalancedBracesException()
+            level=level-1
+            if level == 0:
+                #derniere parenthese fermante
+                return i
diff --git a/Traducteur/removemocle.py b/Traducteur/removemocle.py
new file mode 100644 (file)
index 0000000..66fabd7
--- /dev/null
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+import logging
+from parseur import FactNode
+
+debug=1
+#on n'a qu'un mocle par commande. On peut donc supprimer le mocle sans trop de précautions (a part iterer a l'envers sur les commandes)
+#avant de supprimer un autre mocle, on remet à jour l'arbre syntaxique (lineno,colno,etc.)
+def removemocle(jdc,command,mocle):
+    #on itere sur les commandes a l'envers pour ne pas polluer les numeros de ligne avec les modifications
+    commands= jdc.root.childNodes[:]
+    commands.reverse()
+    for c in commands:
+        if c.name != command:continue
+        for mc in c.childNodes:
+            if mc.name != mocle:continue
+            removemc(jdc,c,mc)
+
+    jdc.reset(jdc.getSource())
+                
+def removemc(jdc,c,mc):
+    if debug:print "Suppression de:",c.name,mc.name,mc.lineno,mc.colno,mc.endline,mc.endcol
+    logging.info("Suppression de: %s, %s, %s, %s, %d, %d",c.name,mc.name,mc.lineno,mc.colno,mc.endline,mc.endcol)
+    if mc.endline > mc.lineno:
+        if debug:print "mocle sur plusieurs lignes--%s--" % jdc.getLines()[mc.lineno-1][mc.colno:]
+        jdc.getLines()[mc.lineno-1]=jdc.getLines()[mc.lineno-1][:mc.colno]
+        jdc.getLines()[mc.endline-1]=jdc.getLines()[mc.endline-1][mc.endcol:]
+        #attention : supprimer les lignes à la fin
+        jdc.getLines()[mc.lineno:mc.endline-1]=[]
+    else:
+        if debug:print "mocle sur une ligne--%s--" % jdc.getLines()[mc.lineno-1][mc.colno:mc.endcol]
+        s=jdc.getLines()[mc.lineno-1]
+        jdc.getLines()[mc.lineno-1]=s[:mc.colno]+s[mc.endcol:]
+
+def removemocleinfact(jdc,command,fact,mocle):
+    #on itere sur les commandes a l'envers pour ne pas polluer les numeros de ligne avec les modifications
+    commands= jdc.root.childNodes[:]
+    commands.reverse()
+    for c in commands:
+        if c.name != command:continue
+        for mc in c.childNodes:
+            if mc.name != fact:continue
+            l=mc.childNodes[:]
+            l.reverse()
+            for ll in l:
+                for n in ll.childNodes:
+                    if n.name != mocle:continue
+                    removemc(jdc,c,n)
+
+    jdc.reset(jdc.getSource())
diff --git a/Traducteur/renamemocle.py b/Traducteur/renamemocle.py
new file mode 100644 (file)
index 0000000..2c98e6f
--- /dev/null
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+import logging
+from parseur import FactNode
+debug=0
+#on n'a qu'un mocle par commande. 
+#en fin de traitement, on remet à jour l'arbre syntaxique (lineno,colno,etc.)
+def renamemocle(jdc,command,mocle,new_name):
+    for c in jdc.root.childNodes:
+        if c.name != command:continue
+        for mc in c.childNodes:
+            if mc.name != mocle:continue
+            if debug:print "Renommage de:",c.name,mc.name,mc.lineno,mc.colno
+            logging.info("Renommage de: %s, %s, %s, %s en %s",c.name,mc.name,mc.lineno,mc.colno,new_name)
+            s=jdc.getLines()[mc.lineno-1]
+            jdc.getLines()[mc.lineno-1]=s[:mc.colno]+new_name+s[mc.colno+len(mocle):]
+
+    jdc.reset(jdc.getSource())
+                
+def renamemocleinfact(jdc,command,fact,mocle,new_name):
+    for c in jdc.root.childNodes:
+        if c.name != command:continue
+        for mc in c.childNodes:
+            if mc.name != fact:continue
+            l=mc.childNodes[:]
+            #on itere a l'envers
+            l.reverse()
+            for ll in l:
+                for n in ll.childNodes:
+                    if n.name != mocle:continue
+                    s=jdc.getLines()[n.lineno-1]
+                    jdc.getLines()[n.lineno-1]=s[:n.colno]+new_name+s[n.colno+len(mocle):]
+
+    jdc.reset(jdc.getSource())
+
diff --git a/Traducteur/toto.comm b/Traducteur/toto.comm
new file mode 100644 (file)
index 0000000..fbd94a1
--- /dev/null
@@ -0,0 +1,74 @@
+DEBUT()
+
+MAIL=LIRE_MAILLAGE(   )
+
+#
+# DEFINITION DES GROUPES DE NOEUDS
+MAIL=DEFI_GROUP( reuse=MAIL,   MAILLAGE=MAIL,CREA_GROUP_NO=(
+                       _F(  GROUP_MA = 'ENCAST'),
+                       _F(  GROUP_MA = 'CONT_PR'),
+                       _F(  GROUP_MA = ( 'B',  'SECT_MED', )))
+                   )
+
+MAIL=DEFI_GROUP( CREA_GROUP_NO=[
+                       _F(  GROUP_MA = 'ENCAST',INFO=2),
+                       _F(  GROUP_MA = 'CONT_PR'),
+                       _F(  GROUP_MA = ( 'B',  'SECT_MED', ))]
+                   )
+#
+# DEFINITION DU MODELE
+MODELE=AFFE_MODELE(    MAILLAGE=MAIL,
+                         AFFE=_F(  TOUT = 'OUI',
+                       PHENOMENE = 'MECANIQUE',
+                       MODELISATION = 'AXIS_FOURIER')  )
+
+#
+# DEFINITION DU MATERIAU
+ACIER=DEFI_MATERIAU(    ELAS= _F( E = 2.1E11,  NU = 0.3,
+                                 ALPHA = 1.E-5,  RHO = 7800.) #comment
+                                 #comment
+                      )
+
+#
+# ATTRIBUTION DU MATERIAU
+CHMAT=AFFE_MATERIAU(    MAILLAGE =MAIL,
+                          AFFE=_F(  TOUT = 'OUI',
+                                 MATER = ACIER)  )
+CHMAT2=AFFE_MATERIAU(    MAILLAGE =MAIL,
+                          AFFE=(_F(  TOUT = 'OUI', MATER = ACIER),
+                                _F(  TOUT = 'OUI', MATER = ACIER),
+                                _F(  TOUT = 'OUI', MATER = ACIER),
+                                )
+                    )
+STAT_NONLINE(SOLVEUR=_F(METHOD="FRONT",
+                        PREC=1.E-3))
+STAT_NONLINE(SOLV=_F(METHOD="FRONT",
+                        PREC=1.E-3),
+             AFFE=(_F(  TOUT = 'OUI', MATER = ACIER),
+                   _F(  TOUT = 'OUI', MATER = ACIER),
+                   _F(  TOUT = 'OUI', MATER = ACIER),
+                  )
+            )
+
+MA=LIRE_MAILLAGE(UNITE=20,INFO=2,TEXT="""aaaa(
+bbb""")
+"""
+MOO=AFFE_MODELE()
+"""
+MO=AFFE_MODELE(MAILLAGE=MA,
+                INFO=2,
+                )
+#LIRE_MAILLAGE()
+MA2=LIRE_MAILLAGE(UNITE=21)
+MA3 = LIRE_MAILLAGE ( #comment ( ]
+                        UNITE=23,
+                     )
+MA4 = LIRE_MAILLAGE ( #commentaire commande
+                   UNITE
+                   =
+                   24
+                   ,INFO=2 #commentaire mocle INFO
+                   ) #commentaire fin commande
+M5=LIRE_MAILLAGE (     #comment commande
+)
+a[2*(i+1)]=LIRE_MAILLAGE(UNITE=21)
diff --git a/Traducteur/utils.py b/Traducteur/utils.py
new file mode 100644 (file)
index 0000000..e14e310
--- /dev/null
@@ -0,0 +1,24 @@
+import re
+
+def indexToCoordinates(src, index):
+    """return le numero de la colonne (x) et le numero de la ligne (y) dans src"""
+    y = src[: index].count("\n")
+    startOfLineIdx = src.rfind("\n", 0, index)+1
+    x = index-startOfLineIdx
+    return x, y
+
+def linetodict(line):
+    """Transforme une ligne (string) en un dictionnaire de mots repérés par le numéro de la colonne"""
+
+    words = re.split("(\w+)", line)
+    h = {};i = 0
+    for word in words:
+        h[i] = word
+        i+=len(word)
+    return h
+
+def dicttoline(d):
+    """Transformation inverse: à partir d'un dictionnaire retourne une ligne"""
+    cols = d.keys()
+    cols.sort()
+    return "".join([d[colno]for colno in cols])
diff --git a/Traducteur/visiteur.py b/Traducteur/visiteur.py
new file mode 100644 (file)
index 0000000..b06ac8e
--- /dev/null
@@ -0,0 +1,61 @@
+import re
+from compiler import visitor
+
+class MatchFinder:
+    """Visiteur de base : gestion des matches """
+    def reset(self,line):
+        self.matches = []
+        self.words = re.split("(\w+)", line) # every other one is a non word
+        self.positions = []
+        i = 0
+        for word in self.words:
+            self.positions.append(i)
+            i+=len(word)
+        self.index = 0
+
+    def popWordsUpTo(self, word):
+        if word == "*":
+            return        # won't be able to find this
+        posInWords = self.words.index(word)
+        idx = self.positions[posInWords]
+        self.words = self.words[posInWords+1:]
+        self.positions = self.positions[posInWords+1:]
+
+    def appendMatch(self,name):
+        idx = self.getNextIndexOfWord(name)
+        self.matches.append((idx, name))
+
+    def getNextIndexOfWord(self,name):
+        return self.positions[self.words.index(name)]
+
+
+class KeywordFinder(MatchFinder):
+    """Visiteur pour les keywords d'une commande """
+
+    def visitKeyword(self,node):
+        idx = self.getNextIndexOfWord(node.name)
+        #self.appendMatch(node.name)
+        self.popWordsUpTo(node.name)
+        prevmatches=self.matches
+        self.matches = []
+        for child in node.getChildNodes():
+            self.visit(child)
+        prevmatches.append((idx, node.name,self.matches))
+        self.matches=prevmatches
+
+    def visitTuple(self,node):
+        matchlist=[]
+        for child in node.getChildNodes():
+            self.matches = []
+            self.visit(child)
+            if self.matches:
+                #Pour eviter les tuples et listes ordinaires, on ne garde que les visites fructueuses
+                matchlist.append(self.matches)
+        self.matches=matchlist
+
+    visitList=visitTuple
+
+    def visitName(self,node):
+        self.popWordsUpTo(node.name)
+    def visitAssName(self,node):
+        self.popWordsUpTo(node.name)