Update German translation
[glib.git] / gio / gdbus-2.0 / codegen / parser.py
blob90cebd961a7b8f7f35447dd8936d061af0c5af8e
1 # -*- Mode: Python -*-
3 # GDBus - GLib D-Bus Library
5 # Copyright (C) 2008-2011 Red Hat, Inc.
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General
18 # Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 # Author: David Zeuthen <davidz@redhat.com>
22 import sys
23 import xml.parsers.expat
25 from . import dbustypes
27 class DBusXMLParser:
28 STATE_TOP = 'top'
29 STATE_NODE = 'node'
30 STATE_INTERFACE = 'interface'
31 STATE_METHOD = 'method'
32 STATE_SIGNAL = 'signal'
33 STATE_PROPERTY = 'property'
34 STATE_ARG = 'arg'
35 STATE_ANNOTATION = 'annotation'
36 STATE_IGNORED = 'ignored'
38 def __init__(self, xml_data):
39 self._parser = xml.parsers.expat.ParserCreate()
40 self._parser.CommentHandler = self.handle_comment
41 self._parser.CharacterDataHandler = self.handle_char_data
42 self._parser.StartElementHandler = self.handle_start_element
43 self._parser.EndElementHandler = self.handle_end_element
45 self.parsed_interfaces = []
46 self._cur_object = None
48 self.state = DBusXMLParser.STATE_TOP
49 self.state_stack = []
50 self._cur_object = None
51 self._cur_object_stack = []
53 self.doc_comment_last_symbol = ''
55 self._parser.Parse(xml_data)
57 COMMENT_STATE_BEGIN = 'begin'
58 COMMENT_STATE_PARAMS = 'params'
59 COMMENT_STATE_BODY = 'body'
60 COMMENT_STATE_SKIP = 'skip'
61 def handle_comment(self, data):
62 comment_state = DBusXMLParser.COMMENT_STATE_BEGIN;
63 lines = data.split('\n')
64 symbol = ''
65 body = ''
66 in_para = False
67 params = {}
68 for line in lines:
69 orig_line = line
70 line = line.lstrip()
71 if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
72 if len(line) > 0:
73 colon_index = line.find(': ')
74 if colon_index == -1:
75 if line.endswith(':'):
76 symbol = line[0:len(line)-1]
77 comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
78 else:
79 comment_state = DBusXMLParser.COMMENT_STATE_SKIP
80 else:
81 symbol = line[0:colon_index]
82 rest_of_line = line[colon_index+2:].strip()
83 if len(rest_of_line) > 0:
84 body += '<para>' + rest_of_line + '</para>'
85 comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
86 elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
87 if line.startswith('@'):
88 colon_index = line.find(': ')
89 if colon_index == -1:
90 comment_state = DBusXMLParser.COMMENT_STATE_BODY
91 if not in_para:
92 body += '<para>'
93 in_para = True
94 body += orig_line + '\n'
95 else:
96 param = line[1:colon_index]
97 docs = line[colon_index + 2:]
98 params[param] = docs
99 else:
100 comment_state = DBusXMLParser.COMMENT_STATE_BODY
101 if len(line) > 0:
102 if not in_para:
103 body += '<para>'
104 in_para = True
105 body += orig_line + '\n'
106 elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
107 if len(line) > 0:
108 if not in_para:
109 body += '<para>'
110 in_para = True
111 body += orig_line + '\n'
112 else:
113 if in_para:
114 body += '</para>'
115 in_para = False
116 if in_para:
117 body += '</para>'
119 if symbol != '':
120 self.doc_comment_last_symbol = symbol
121 self.doc_comment_params = params
122 self.doc_comment_body = body
124 def handle_char_data(self, data):
125 #print 'char_data=%s'%data
126 pass
128 def handle_start_element(self, name, attrs):
129 old_state = self.state
130 old_cur_object = self._cur_object
131 if self.state == DBusXMLParser.STATE_IGNORED:
132 self.state = DBusXMLParser.STATE_IGNORED
133 elif self.state == DBusXMLParser.STATE_TOP:
134 if name == DBusXMLParser.STATE_NODE:
135 self.state = DBusXMLParser.STATE_NODE
136 else:
137 self.state = DBusXMLParser.STATE_IGNORED
138 elif self.state == DBusXMLParser.STATE_NODE:
139 if name == DBusXMLParser.STATE_INTERFACE:
140 self.state = DBusXMLParser.STATE_INTERFACE
141 iface = dbustypes.Interface(attrs['name'])
142 self._cur_object = iface
143 self.parsed_interfaces.append(iface)
144 elif name == DBusXMLParser.STATE_ANNOTATION:
145 self.state = DBusXMLParser.STATE_ANNOTATION
146 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
147 self._cur_object.annotations.append(anno)
148 self._cur_object = anno
149 else:
150 self.state = DBusXMLParser.STATE_IGNORED
152 # assign docs, if any
153 if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']:
154 self._cur_object.doc_string = self.doc_comment_body
155 if 'short_description' in self.doc_comment_params:
156 short_description = self.doc_comment_params['short_description']
157 self._cur_object.doc_string_brief = short_description
158 if 'since' in self.doc_comment_params:
159 self._cur_object.since = \
160 self.doc_comment_params['since'].strip()
162 elif self.state == DBusXMLParser.STATE_INTERFACE:
163 if name == DBusXMLParser.STATE_METHOD:
164 self.state = DBusXMLParser.STATE_METHOD
165 method = dbustypes.Method(attrs['name'])
166 self._cur_object.methods.append(method)
167 self._cur_object = method
168 elif name == DBusXMLParser.STATE_SIGNAL:
169 self.state = DBusXMLParser.STATE_SIGNAL
170 signal = dbustypes.Signal(attrs['name'])
171 self._cur_object.signals.append(signal)
172 self._cur_object = signal
173 elif name == DBusXMLParser.STATE_PROPERTY:
174 self.state = DBusXMLParser.STATE_PROPERTY
175 prop = dbustypes.Property(attrs['name'], attrs['type'], attrs['access'])
176 self._cur_object.properties.append(prop)
177 self._cur_object = prop
178 elif name == DBusXMLParser.STATE_ANNOTATION:
179 self.state = DBusXMLParser.STATE_ANNOTATION
180 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
181 self._cur_object.annotations.append(anno)
182 self._cur_object = anno
183 else:
184 self.state = DBusXMLParser.STATE_IGNORED
186 # assign docs, if any
187 if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']:
188 self._cur_object.doc_string = self.doc_comment_body
189 if 'since' in self.doc_comment_params:
190 self._cur_object.since = \
191 self.doc_comment_params['since'].strip()
193 elif self.state == DBusXMLParser.STATE_METHOD:
194 if name == DBusXMLParser.STATE_ARG:
195 self.state = DBusXMLParser.STATE_ARG
196 arg_name = None
197 if 'name' in attrs:
198 arg_name = attrs['name']
199 arg = dbustypes.Arg(arg_name, attrs['type'])
200 direction = attrs.get('direction', 'in')
201 if direction == 'in':
202 self._cur_object.in_args.append(arg)
203 elif direction == 'out':
204 self._cur_object.out_args.append(arg)
205 else:
206 raise RuntimeError('Invalid direction "%s"'%(direction))
207 self._cur_object = arg
208 elif name == DBusXMLParser.STATE_ANNOTATION:
209 self.state = DBusXMLParser.STATE_ANNOTATION
210 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
211 self._cur_object.annotations.append(anno)
212 self._cur_object = anno
213 else:
214 self.state = DBusXMLParser.STATE_IGNORED
216 # assign docs, if any
217 if self.doc_comment_last_symbol == old_cur_object.name:
218 if 'name' in attrs and attrs['name'] in self.doc_comment_params:
219 doc_string = self.doc_comment_params[attrs['name']]
220 if doc_string != None:
221 self._cur_object.doc_string = doc_string
222 if 'since' in self.doc_comment_params:
223 self._cur_object.since = \
224 self.doc_comment_params['since'].strip()
226 elif self.state == DBusXMLParser.STATE_SIGNAL:
227 if name == DBusXMLParser.STATE_ARG:
228 self.state = DBusXMLParser.STATE_ARG
229 arg_name = None
230 if 'name' in attrs:
231 arg_name = attrs['name']
232 arg = dbustypes.Arg(arg_name, attrs['type'])
233 self._cur_object.args.append(arg)
234 self._cur_object = arg
235 elif name == DBusXMLParser.STATE_ANNOTATION:
236 self.state = DBusXMLParser.STATE_ANNOTATION
237 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
238 self._cur_object.annotations.append(anno)
239 self._cur_object = anno
240 else:
241 self.state = DBusXMLParser.STATE_IGNORED
243 # assign docs, if any
244 if self.doc_comment_last_symbol == old_cur_object.name:
245 if 'name' in attrs and attrs['name'] in self.doc_comment_params:
246 doc_string = self.doc_comment_params[attrs['name']]
247 if doc_string != None:
248 self._cur_object.doc_string = doc_string
249 if 'since' in self.doc_comment_params:
250 self._cur_object.since = \
251 self.doc_comment_params['since'].strip()
253 elif self.state == DBusXMLParser.STATE_PROPERTY:
254 if name == DBusXMLParser.STATE_ANNOTATION:
255 self.state = DBusXMLParser.STATE_ANNOTATION
256 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
257 self._cur_object.annotations.append(anno)
258 self._cur_object = anno
259 else:
260 self.state = DBusXMLParser.STATE_IGNORED
262 elif self.state == DBusXMLParser.STATE_ARG:
263 if name == DBusXMLParser.STATE_ANNOTATION:
264 self.state = DBusXMLParser.STATE_ANNOTATION
265 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
266 self._cur_object.annotations.append(anno)
267 self._cur_object = anno
268 else:
269 self.state = DBusXMLParser.STATE_IGNORED
271 elif self.state == DBusXMLParser.STATE_ANNOTATION:
272 if name == DBusXMLParser.STATE_ANNOTATION:
273 self.state = DBusXMLParser.STATE_ANNOTATION
274 anno = dbustypes.Annotation(attrs['name'], attrs['value'])
275 self._cur_object.annotations.append(anno)
276 self._cur_object = anno
277 else:
278 self.state = DBusXMLParser.STATE_IGNORED
280 else:
281 raise RuntimeError('Unhandled state "%s" while entering element with name "%s"'%(self.state, name))
283 self.state_stack.append(old_state)
284 self._cur_object_stack.append(old_cur_object)
286 def handle_end_element(self, name):
287 self.state = self.state_stack.pop()
288 self._cur_object = self._cur_object_stack.pop()
290 def parse_dbus_xml(xml_data):
291 parser = DBusXMLParser(xml_data)
292 return parser.parsed_interfaces