1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import re
18
21
23 re_xml = re.compile('''<[?]xml([^?]*)[?]>''')
24 re_comment = re.compile('''<!--(-*)''')
25 re_tag = re.compile('''<\s*([^/]\S*)(.*)>''')
26 re_tag_close = re.compile('''</\s*(\S+)\s*>''')
27
28 re_attr = re.compile('''\S+="[^"]*"''')
29
31 if isinstance(lines, basestring):
32 lines = lines.split("\n")
33 self.lines = lines
34 self.lineno = 0
35 self.xmlAttrs = None
36
39
41 if v == "":
42
43 return v
44 vlower = v.lower()
45 if vlower in ["null", "none"]:
46 return None
47 if vlower == "true":
48 return True
49 if vlower == "false":
50 return False
51 try:
52 v = int(v)
53 return v
54 except:
55 pass
56 try:
57 v = float(v)
58 return v
59 except:
60 pass
61 if len(v) > 1:
62 if v[0] == v[-1]:
63 if unpackStr and v[0] in ["'", '"']:
64 return v[1:-1]
65 elif v[0] == '(' and v[-1] == ')':
66 values = []
67 try:
68 for value in v[1:-1].split(','):
69 value = self.parseValue(value.strip(), True)
70 values.append(value)
71 return tuple(values)
72 except:
73 pass
74 if len(v) > 2:
75 if v[:2] == "u'" and v[-1] == "'":
76 return v[2:-1]
77 if v[:2] == 'u"' and v[-1] == '"':
78 return v[2:-1]
79 return v
80
82 attrs = {}
83
84
85 for kv in self.re_attr.findall(line):
86 k, v = kv.split("=", 1)
87 k = k.strip()
88 v = v.replace("%22;", '"')
89 v = v.replace("%0A;", "\n")
90 v = v.strip()[1:-1]
91 attrs[k] = self.parseValue(v)
92 return attrs
93
94 - def getTag(self, line, requiredTags=None):
95 mTag = self.re_tag.match(line)
96 if ( not mTag
97 or ( requiredTags is not None
98 and mTag.group(1) not in requiredTags
99 )
100 ):
101 if requiredTags is not None:
102 self.error("Expected tag %s" % ",".join(requiredTags))
103 else:
104 self.error("Expected a tag")
105 tagName = mTag.group(1)
106 tagAttrs = mTag.group(2)
107 if tagAttrs and tagAttrs[-1] == "/":
108 tagAttrs = tagAttrs[:-1]
109 tagClose = True
110 else:
111 tagClose = False
112 return (tagName, tagClose, self.getAttrs(tagAttrs))
113
115 mTag = self.re_tag_close.match(line)
116 if not mTag or (tag is not None and mTag.group(1) != tag):
117 if tag is not None:
118 self.error("Expected closing tag '%s'" % tag)
119 else:
120 self.error("Expected a closing tag")
121 return (
122 mTag.group(1),
123 )
124
126 if self.lineno > len(self.lines):
127 return None
128 line = self.lines[self.lineno].strip()
129 startlineno = self.lineno
130 mComment = self.re_comment.search(line)
131 while mComment:
132 start = '<!--%s' % mComment.group(1)
133 end = '%s-->' % mComment.group(1)
134 left = line.find(start) + len(start)
135 right = line.find(end, left)
136 if right >= left:
137 right += len(end)
138 line = line[:left - len(start)] + line[right + len(end):]
139 mComment = self.re_comment.search(line)
140 elif self.lineno == len(self.lines):
141 self.error(
142 "Unterminated comment starting at line %s" % startlineno,
143 )
144 else:
145 self.lineno += 1
146 line = line[:left] + self.lines[self.lineno].strip()
147 return line
148
150 if self.lineno > len(self.lines):
151 return None
152 line = self.currentLine()
153 self.lineno += 1
154 return line
155
157 line = self.currentLine()
158 mTag = self.re_tag_close.match(line)
159 if mTag and mTag.group(1) == tagName:
160 return True
161 return False
162
164 line = self.nextLine()
165 tag = self.getTag(line, requiredTags)
166 if self.isTagClose(tag[0]):
167 line = self.nextLine()
168 tag = (tag[0], True) + tag[2:]
169 tagFunc = "tag_%s" % tag[0]
170 if hasattr(self, tagFunc):
171 return getattr(self, tagFunc)(tag)
172 self.error("Unknown tag '%s'" % tag[0])
173
175 line = self.currentLine()
176 mXML = self.re_xml.match(line)
177 if mXML:
178 xmlAttrs = mXML.group(1)
179 self.xmlAttrs = self.getAttrs(xmlAttrs)
180 line = self.nextLine()
181 rootTag = None
182 properties = self.nextTag(["pyjsglade", "properties", "components"])
183 if properties[0] == 'pyjsglade':
184 rootTag = properties[0]
185 properties = self.nextTag(["properties", "components"])
186 if properties[0] == 'properties':
187 properties = properties[2]
188 components = self.nextTag(["components"])[1]
189 else:
190 components = properties[1]
191 properties = {}
192 if rootTag is not None:
193 line = self.nextLine()
194 self.getTagClose(line, rootTag)
195 return properties, components
196
199
201 tags = []
202 tagName, tagClosed, tagAttrs = tag
203 if not tagClosed:
204 while not self.isTagClose(tagName):
205 tags.append(self.nextTag(["component"]))
206 line = self.nextLine()
207 self.getTagClose(line, tagName)
208 components = []
209 for tag in tags:
210 components.append((tag[1]["index"], tag[1:]))
211 components.sort()
212 return tagName, [c[1] for c in components]
213
215 tags = []
216 tagName, tagClosed, tagAttrs = tag
217 if not tagClosed:
218 while not self.isTagClose(tagName):
219 tags.append(self.nextTag(["properties", "components"]))
220 line = self.nextLine()
221 self.getTagClose(line, tagName)
222 props = {}
223 childs = []
224 for tag in tags:
225 if tag[0] == 'properties':
226 name = tag[1]["name"]
227 if not name in props:
228 props[name] = {}
229 props[name].update(tag[2])
230 elif tag[0] == 'components':
231 childs += tag[1]
232 else:
233 assert("Unknown tag found: %s" % repr(tag[0]))
234 return tagName, tagAttrs, props, childs
235
237 tags = []
238 tagName, tagClosed, tagAttrs = tag
239 if not tagClosed:
240 while not self.isTagClose(tagName):
241 tags.append(self.nextTag(["properties", "property"]))
242 line = self.nextLine()
243 self.getTagClose(line, tagName)
244
245 props = {}
246 for tag in tags:
247 if tag[0] == "properties":
248 props[tag[1]["name"]] = tag[2]
249 else:
250 props.update(tag[1])
251 return tagName, tagAttrs, props
252
254 tags = []
255 tagName, tagClosed, tagAttrs = tag
256 if not tagClosed:
257 line = self.nextLine()
258 self.getTagClose(line, tagName)
259 return tagName, {tag[2]["name"]: tag[2]["value"]}
260
261
262 if __name__ == '__main__':
263 import sys
264 lines = open(sys.argv[1]).read()
265 xmlFile = XMLFile(lines)
266 tagName, components = xmlFile.parse()
267
268 - def dump(component):
269 print "component:", component[0], component[1]
270 for c in component[2]:
271 dump(c)
272 for component in components:
273 print "Frame:", component[0], component[1]
274 for c in component[2]:
275 dump(c)
276