1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013 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
25 escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
26 stringsAndCommentsRE = \
27 re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
28 allchars = string.maketrans("", "")
29 allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
30 allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
32 #------------------------------
33 def maskStringsAndComments(src):
34 #------------------------------
35 """Remplace tous les caracteres dans commentaires et strings par des * """
37 src = escapedQuotesRE.sub("**", src)
38 allstrings = stringsAndCommentsRE.split(src)
39 # every odd element is a string or comment
40 for i in xrange(1, len(allstrings), 2):
41 if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
42 allstrings[i] = allstrings[i][:3]+ \
43 allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
46 allstrings[i] = allstrings[i][0]+ \
47 allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
50 return "".join(allstrings)
52 #un nombre queconque de blancs,un nom,des blancs
53 pattern_oper = re.compile(r"^\s*(.*?=\s*)?([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
54 pattern_proc = re.compile(r"^\s*([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
56 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
57 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
58 emptyHangingBraces = [0,0,0,0,0]
60 #--------------------------------------
61 class UnbalancedBracesException: pass
62 #--------------------------------------
70 def addChild(self,node):
71 self.childNodes.append(node)
83 def __init__(self,src):
90 def __init__(self,name,lineno,colno,firstparen):
95 self.firstparen=firstparen
100 def __init__(self,name,lineno,colno,endline,endcol):
108 def getText(self,jdc):
109 if self.endline > self.lineno:
110 debut=jdc.getLines()[self.lineno-1][self.colno:]
111 fin = jdc.getLines()[self.endline-1][:self.endcol]
113 lignecourante=self.lineno
114 while lignecourante < self.endline -1 :
115 texte = texte + jdc.getLines()[lignecourante]
116 lignecourante = lignecourante + 1
117 if chaineBlanche(fin) == 0 :
119 if texte[-1] == "\n" :
122 texte = jdc.getLines()[self.lineno-1][self.colno:self.endcol]
125 #-------------------------
126 def chaineBlanche(texte) :
127 #-------------------------
128 # retourne 1 si la chaine est composee de " "
131 for i in range(len(texte)) :
132 if texte[i] != " " : bool = 0
138 if hasattr(node,'name'):
141 print "pas de nom pour:",node
142 for c in node.childNodes:
145 #------------------------
146 def Parser(src,atraiter):
147 #------------------------
148 """Parse le texte src et retourne un arbre syntaxique (root).
150 Cet arbre syntaxique a comme noeuds (childNodes) les commandes à traiter (liste atraiter)
152 lines=src.splitlines(1)
153 maskedSrc=maskStringsAndComments(src)
154 maskedLines=maskedSrc.splitlines(1)
158 # (a) dans un premier temps on extrait les commandes et on les insère
159 # dans un arbre (root) les noeuds fils sont stockés dans
160 # root.childNodes (liste)
162 for line in maskedLines:
164 if debug:print "line",lineno,":",line
165 m=pattern_proc.match(line)
166 if m and (m.group(1) in atraiter):
167 if debug:print m.start(3),m.end(3),m.start(4)
168 root.addChild(Command(m.group(1),lineno,m.start(1),m.end(3)))
170 m=pattern_oper.match(line)
171 if m and (m.group(2) in atraiter):
172 root.addChild(Command(m.group(2),lineno,m.start(2),m.end(4)))
174 #(b) dans un deuxième temps , on récupère le texte complet de la commande
175 # jusqu'à la dernière parenthèse fermante
177 # iterateur sur les lignes physiques masquées
178 iterlines=iter(maskedLines)
181 for c in root.childNodes:
183 colno=c.colno # début de la commande
184 while linenum < lineno:
185 line=iterlines.next()
187 if linenum != lineno:
188 if debug:print "line %s:"%linenum, line
190 hangingBraces = list(emptyHangingBraces)
193 # update hanging braces
194 for i in range(len(implicitContinuationChars)):
195 contchar = implicitContinuationChars[i]
196 numHanging = hangingBraces[i]
198 hangingBraces[i] = numHanging+line.count(contchar[0]) - \
199 line.count(contchar[1])
201 hangingComments ^= line.count('"""') % 2
202 hangingComments ^= line.count("'''") % 2
204 if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0:
205 raise UnbalancedBracesException()
207 if linecontinueRE.search(line):
208 tmp.append(lines[linenum-1])
209 elif hangingBraces != emptyHangingBraces:
210 tmp.append(lines[linenum-1])
211 elif hangingComments:
212 tmp.append(lines[linenum-1])
214 tmp.append(lines[linenum-1])
218 decal=len(line)-line.rindex(')')
219 c.lastparen=len(src)-decal
220 if debug:print "logical line %s %s:" % (c.lineno,c.endline),src
222 line=iterlines.next()
231 """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
233 La string doit contenir la premiere parenthese ouvrante
236 src=maskStringsAndComments(src)
246 raise UnbalancedBracesException()
249 #derniere parenthese fermante
255 """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
257 La string ne contient pas la premiere parenthese ouvrante
259 src=maskStringsAndComments(src)
269 raise UnbalancedBracesException()
272 #derniere parenthese fermante