]> SALOME platform Git repositories - tools/eficas.git/blob - Traducteur/parseur.py
Salome HOME
fead5e6ce9a203e22e29f953271a220eebed16bb
[tools/eficas.git] / Traducteur / parseur.py
1 # -*- coding: utf-8 -*-
2 import re,string
3 import compiler
4
5 debug=0
6
7 escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
8 stringsAndCommentsRE =  \
9       re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
10 allchars = string.maketrans("", "")
11 allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
12 allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
13
14 #------------------------------
15 def maskStringsAndComments(src):
16 #------------------------------
17     """Remplace tous les caracteres dans commentaires et strings par des * """
18
19     src = escapedQuotesRE.sub("**", src)
20     allstrings = stringsAndCommentsRE.split(src)
21     # every odd element is a string or comment
22     for i in xrange(1, len(allstrings), 2):
23         if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
24             allstrings[i] = allstrings[i][:3]+ \
25                            allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
26                            allstrings[i][-3:]
27         else:
28             allstrings[i] = allstrings[i][0]+ \
29                            allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
30                            allstrings[i][-1]
31
32     return "".join(allstrings)
33
34 #un nombre queconque de blancs,un nom,des blancs
35 pattern_oper   = re.compile(r"^\s*(.*?=\s*)?([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
36 pattern_proc   = re.compile(r"^\s*([a-zA-Z_]\w*)(\s*)(\()(.*)",re.DOTALL)
37
38 implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
39 linecontinueRE = re.compile(r"\\\s*(#.*)?$")
40 emptyHangingBraces = [0,0,0,0,0]
41
42 #--------------------------------------
43 class UnbalancedBracesException: pass
44 #--------------------------------------
45
46 #-----------
47 class Node:
48 #-----------
49     def __init__(self):
50         self.childNodes=[]
51
52     def addChild(self,node):
53         self.childNodes.append(node)
54
55
56 #-------------------
57 class FactNode(Node):
58 #-------------------
59     pass
60
61
62 #-------------------
63 class JDCNode(Node):
64 #-------------------
65     def __init__(self,src):
66         Node.__init__(self)
67         self.src=src
68
69 #-------------------
70 class Command(Node):
71 #-------------------
72     def __init__(self,name,lineno,colno,firstparen):
73         Node.__init__(self)
74         self.name=name
75         self.lineno=lineno
76         self.colno=colno
77         self.firstparen=firstparen
78
79 #-------------------
80 class Keyword(Node):
81 #-------------------
82     def __init__(self,name,lineno,colno,endline,endcol):
83         Node.__init__(self)
84         self.name=name
85         self.lineno=lineno
86         self.colno=colno
87         self.endline=endline
88         self.endcol=endcol
89
90     def getText(self,jdc):
91         if self.endline > self.lineno:
92             debut=jdc.getLines()[self.lineno-1][self.colno:]
93             fin  = jdc.getLines()[self.endline-1][:self.endcol]
94             texte=debut
95             lignecourante=self.lineno  
96             while  lignecourante < self.endline -1  :
97                 texte = texte + jdc.getLines()[lignecourante]
98                 lignecourante = lignecourante + 1
99             if chaineBlanche(fin) == 0 :  
100                texte=texte + fin
101             if texte[-1] == "\n" :
102                texte=texte[0:-1]
103         else:
104             texte = jdc.getLines()[self.lineno-1][self.colno:self.endcol]
105         return texte
106
107 #-------------------------
108 def chaineBlanche(texte) :
109 #-------------------------
110 # retourne 1 si la chaine est composee de " "
111 # retourne 0 sinon
112     bool = 1 ;
113     for i in range(len(texte)) :
114         if texte[i] != " " : bool = 0
115     return bool
116
117 #-------------------
118 def printNode(node):
119 #-------------------
120     if hasattr(node,'name'):
121         print node.name
122     else:
123         print "pas de nom pour:",node
124     for c in node.childNodes:
125         printNode(c)
126
127 #------------------------
128 def Parser(src,atraiter):
129 #------------------------
130     """Parse le texte src et retourne un arbre syntaxique (root).
131
132        Cet arbre syntaxique a comme noeuds (childNodes) les commandes à traiter (liste atraiter)
133     """
134     lines=src.splitlines(1)
135     maskedSrc=maskStringsAndComments(src)
136     maskedLines=maskedSrc.splitlines(1)
137
138     root=JDCNode(src)
139
140     # (a) dans un premier temps on extrait les commandes et on les insère 
141     #     dans un arbre (root)  les noeuds fils sont stockés dans 
142     #     root.childNodes (liste)
143     lineno=0
144     for line in maskedLines:
145         lineno=lineno+1
146         if debug:print "line",lineno,":",line
147         m=pattern_proc.match(line)
148         if m and (m.group(1) in atraiter):
149             if debug:print m.start(3),m.end(3),m.start(4)
150             root.addChild(Command(m.group(1),lineno,m.start(1),m.end(3)))
151         else:
152             m=pattern_oper.match(line)
153             if m and (m.group(2) in atraiter):
154                 root.addChild(Command(m.group(2),lineno,m.start(2),m.end(4)))
155
156     #(b) dans un deuxième temps , on récupère le texte complet de la commande 
157     #    jusqu'à la  dernière parenthèse fermante
158
159     # iterateur sur les lignes physiques masquées
160     iterlines=iter(maskedLines)
161
162     linenum=0
163     for c in root.childNodes:
164         lineno=c.lineno
165         colno=c.colno                       # début de la commande
166         while linenum < lineno:
167             line=iterlines.next()
168             linenum=linenum+1
169             if linenum != lineno:
170                 if debug:print "line %s:"%linenum, line
171         tmp = []
172         hangingBraces = list(emptyHangingBraces)
173         hangingComments = 0
174         while 1:
175             # update hanging braces
176             for i in range(len(implicitContinuationChars)):
177                 contchar = implicitContinuationChars[i]
178                 numHanging = hangingBraces[i]
179
180                 hangingBraces[i] = numHanging+line.count(contchar[0]) - \
181                                 line.count(contchar[1])
182
183             hangingComments ^= line.count('"""') % 2
184             hangingComments ^= line.count("'''") % 2
185     
186             if hangingBraces[0] < 0 or hangingBraces[1] < 0 or hangingBraces[2] < 0:
187                 raise UnbalancedBracesException()
188
189             if linecontinueRE.search(line):
190                 tmp.append(lines[linenum-1])
191             elif hangingBraces != emptyHangingBraces:
192                 tmp.append(lines[linenum-1])
193             elif hangingComments:
194                 tmp.append(lines[linenum-1])
195             else:
196                 tmp.append(lines[linenum-1])
197                 src="".join(tmp)
198                 c.src=src
199                 c.endline=linenum
200                 decal=len(line)-line.rindex(')')
201                 c.lastparen=len(src)-decal
202                 if debug:print "logical line %s %s:" % (c.lineno,c.endline),src
203                 break
204             line=iterlines.next()
205             linenum=linenum+1
206
207     return root
208
209
210 #-----------------
211 def lastparen(src):
212 #-----------------
213     """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
214
215        La string doit contenir la premiere parenthese ouvrante
216     """
217
218     src=maskStringsAndComments(src)
219     level=0
220     i,n=0,len(src)
221     while i < n:
222         ch=src[i]
223         i=i+1
224         if ch in ('(','['):
225             level=level+1
226         if ch in (')',']'):
227             if level == 0:
228                 raise UnbalancedBracesException()
229             level=level-1
230             if level == 0:
231                 #derniere parenthese fermante
232                 return i
233
234 #-------------------
235 def lastparen2(src):
236 #-------------------
237     """Retourne la position de la derniere parenthese fermante dans src a partir du debut de la string
238
239        La string ne contient pas la premiere parenthese ouvrante
240     """
241     src=maskStringsAndComments(src)
242     level=1
243     i,n=0,len(src)
244     while i < n:
245         ch=src[i]
246         i=i+1
247         if ch in ('(','['):
248             level=level+1
249         if ch in (')',']'):
250             if level == 0:
251                 raise UnbalancedBracesException()
252             level=level-1
253             if level == 0:
254                 #derniere parenthese fermante
255                 return i
256