1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2017 EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
25 stringsAndCommentsRE = \
26 re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
30 allchars = string.maketrans(u"", "")
31 allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
32 allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
34 allchars=bytes.maketrans(b"",b"")
35 allcharsExceptNewline = allchars[: allchars.index(b'\n')]+allchars[allchars.index(b'\n')+1:]
36 allcharsExceptNewlineTranstable = bytes.maketrans(allcharsExceptNewline, b'*'*len(allcharsExceptNewline))
39 #------------------------------
40 def maskStringsAndComments(src):
41 #------------------------------
42 """Remplace tous les caracteres dans commentaires et strings par des * """
44 src = escapedQuotesRE.sub("**", src)
45 allstrings = stringsAndCommentsRE.split(src)
46 # every odd element is a string or comment
47 for i in range(1, len(allstrings), 2):
48 if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
49 allstrings[i] = allstrings[i][:3]+ \
50 allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
53 allstrings[i] = allstrings[i][0]+ \
54 allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
57 return "".join(allstrings)
59 #un nombre queconque de blancs,un nom,des blancs
60 pattern_oper = re.compile(r"^\s*(.*?=\s*)?([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
61 pattern_proc = re.compile(r"^\s*([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
63 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
64 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
65 emptyHangingBraces = [0,0,0,0,0]
67 #--------------------------------------
68 class UnbalancedBracesException: pass
69 #--------------------------------------
77 def addChild(self,node):
78 self.childNodes.append(node)
90 def __init__(self,src):
97 def __init__(self,name,lineno,colno,firstparen):
102 self.firstparen=firstparen
107 def __init__(self,name,lineno,colno,endline,endcol):
115 def getText(self,jdc):
116 if self.endline > self.lineno:
117 debut=jdc.getLines()[self.lineno-1][self.colno:]
118 fin = jdc.getLines()[self.endline-1][:self.endcol]
120 lignecourante=self.lineno
121 while lignecourante < self.endline -1 :
122 texte = texte + jdc.getLines()[lignecourante]
123 lignecourante = lignecourante + 1
124 if chaineBlanche(fin) == 0 :
126 if texte[-1] == "\n" :
129 texte = jdc.getLines()[self.lineno-1][self.colno:self.endcol]
132 #-------------------------
133 def chaineBlanche(texte) :
134 #-------------------------
135 # retourne 1 si la chaine est composee de " "
138 for i in range(len(texte)) :
139 if texte[i] != " " : bool = 0
145 if hasattr(node,'name'):
148 print ("pas de nom pour:",node)
149 for c in node.childNodes:
152 #------------------------
153 def parser(src,atraiter):
154 #------------------------
155 """Parse le texte src et retourne un arbre syntaxique (root).
157 Cet arbre syntaxique a comme noeuds (childNodes) les commandes a traiter (liste atraiter)
159 lines=src.splitlines(1)
160 maskedSrc=maskStringsAndComments(src)
161 maskedLines=maskedSrc.splitlines(1)
165 # (a) dans un premier temps on extrait les commandes et on les insere
166 # dans un arbre (root) les noeuds fils sont stockes dans
167 # root.childNodes (liste)
169 for line in maskedLines:
171 if debug:print ("line",lineno,":",line)
172 m=pattern_proc.match(line)
173 if m and (m.group(1) in atraiter):
174 if debug:print (m.start(3),m.end(3),m.start(4))
175 root.addChild(Command(m.group(1),lineno,m.start(1),m.end(3)))
177 m=pattern_oper.match(line)
178 if m and (m.group(2) in atraiter):
179 root.addChild(Command(m.group(2),lineno,m.start(2),m.end(4)))
181 #(b) dans un deuxieme temps , on recupere le texte complet de la commande
182 # jusqu'a la derniere parenthese fermante
184 # iterateur sur les lignes physiques masquees
185 iterlines=iter(maskedLines)
188 for c in root.childNodes:
190 colno=c.colno # debut de la commande
191 while linenum < lineno:
192 line=iterlines.__next__()
194 if linenum != lineno:
195 if debug:print ("line %s:"%linenum, line)
197 hangingBraces = list(emptyHangingBraces)
200 # update hanging braces
201 for i in range(len(implicitContinuationChars)):
202 contchar = implicitContinuationChars[i]
203 numHanging = hangingBraces[i]
205 hangingBraces[i] = numHanging+line.count(contchar[0]) - \
206 line.count(contchar[1])
208 hangingComments ^= line.count('"""') % 2
209 hangingComments ^= line.count("'''") % 2
211 if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0:
212 raise UnbalancedBracesException()
214 if linecontinueRE.search(line):
215 tmp.append(lines[linenum-1])
216 elif hangingBraces != emptyHangingBraces:
217 tmp.append(lines[linenum-1])
218 elif hangingComments:
219 tmp.append(lines[linenum-1])
221 tmp.append(lines[linenum-1])
225 decal=len(line)-line.rindex(')')
226 c.lastParen=len(src)-decal
227 if debug:print ("logical line %s %s:" % (c.lineno,c.endline),src)
229 line=iterlines.__next__()
238 """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
240 La string doit contenir la premiere parenthese ouvrante
243 src=maskStringsAndComments(src)
253 raise UnbalancedBracesException()
256 #derniere parenthese fermante
262 """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
264 La string ne contient pas la premiere parenthese ouvrante
266 src=maskStringsAndComments(src)
276 raise UnbalancedBracesException()
279 #derniere parenthese fermante