blob: d2b7d8024e12363b5d3d7cacaecf426a78782399 [file] [log] [blame]
Dusan Klinecccaa0d92014-11-09 03:21:31 +01001__author__ = "Dusan (Ph4r05) Klinec"
2__copyright__ = "Copyright (C) 2014 Dusan (ph4r05) Klinec"
3__license__ = "Apache License, Version 2.0"
4__version__ = "1.0"
5
Dusan Klinece26bb022014-11-09 12:21:37 +01006class Visitor(object):
7
8 def __init__(self, verbose=False):
9 self.verbose = verbose
10
11 def __getattr__(self, name):
12 if not name.startswith('visit_'):
Dusan Klinecc9b031a2014-11-10 13:21:08 +010013 raise AttributeError('name must start with visit_ but was {}'.format(name))
Dusan Klinece26bb022014-11-09 12:21:37 +010014
15 def f(element):
16 if self.verbose:
17 msg = 'unimplemented call to {}; ignoring ({})'
18 print(msg.format(name, element))
19 return True
20 return f
21
22 # visitor.visit_PackageStatement(self)
23 # visitor.visit_ImportStatement(self)
24 # visitor.visit_OptionStatement(self)
25 # visitor.visit_FieldDirective(self)
26 # visitor.visit_FieldType(self)
27 # visitor.visit_FieldDefinition(self)
28 # visitor.visit_EnumFieldDefinition(self)
29 # visitor.visit_EnumDefinition(self)
30 # visitor.visit_MessageDefinition(self)
31 # visitor.visit_MessageExtension(self)
32 # visitor.visit_MethodDefinition(self)
33 # visitor.visit_ServiceDefinition(self)
34 # visitor.visit_ExtensionsDirective(self)
35 # visitor.visit_Literal(self)
36 # visitor.visit_Name(self)
Dusan Klinecc9b031a2014-11-10 13:21:08 +010037 # visitor.visit_Proto(self)
Dusan Klineca9f6d362014-11-10 21:07:08 +010038 # visitor.visit_LU(self)
39
40class Base(object):
41 parent = None
42
43 def v(self, obj, visitor):
44 if obj == None:
45 return
46 if not hasattr(obj, "accept"):
47 return
48 obj.accept(visitor)
Dusan Klinece26bb022014-11-09 12:21:37 +010049
Dusan Klinecaa9ff472014-11-10 18:02:03 +010050# Lexical unit - contains lexspan and linespan for later analysis.
Dusan Klineca9f6d362014-11-10 21:07:08 +010051class LU(Base):
Dusan Klinecaa9ff472014-11-10 18:02:03 +010052 def __init__(self, p, idx):
53 self.p = p
54 self.idx = idx
55 self.pval = p[idx]
56 self.lexspan = p.lexspan(idx)
57 self.linespan = p.linespan(idx)
58
59 # If string is in the value (raw value) and start and stop lexspan is the same, add real span
60 # obtained by string length.
61 if isinstance(self.pval, str) \
62 and self.lexspan != None \
63 and self.lexspan[0] == self.lexspan[1] \
64 and self.lexspan[0] != 0:
65 self.lexspan = tuple([self.lexspan[0], self.lexspan[0] + len(self.pval)])
66 super(LU, self).__init__()
67
68 @staticmethod
69 def i(p, idx):
70 if isinstance(p[idx], LU): return p[idx]
71 if isinstance(p[idx], str): return LU(p, idx)
72 return p[idx]
73
74 def describe(self):
75 return "LU(%s,%s)" % (self.pval, self.lexspan)
76
77 def __str__(self):
78 return self.pval
79
80 def __repr__(self):
81 return self.describe()
82
83 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +010084 self.v(self.pval, visitor)
Dusan Klinecaa9ff472014-11-10 18:02:03 +010085
86 def __iter__(self):
87 for x in self.pval:
88 yield x
89
Dusan Klinecccaa0d92014-11-09 03:21:31 +010090# Base node
Dusan Klineca9f6d362014-11-10 21:07:08 +010091class SourceElement(Base):
Dusan Klinecccaa0d92014-11-09 03:21:31 +010092 '''
Dusan Klinece26bb022014-11-09 12:21:37 +010093 A SourceElement is the base class for all elements that occur in a Protocol Buffers
94 file parsed by plyproto.
Dusan Klinecccaa0d92014-11-09 03:21:31 +010095 '''
Dusan Klinecc9b031a2014-11-10 13:21:08 +010096 def __init__(self, linespan=[], lexspan=[], p=None):
Dusan Klinecccaa0d92014-11-09 03:21:31 +010097 super(SourceElement, self).__init__()
Dusan Klinecc9b031a2014-11-10 13:21:08 +010098 self._fields = [] # ['linespan', 'lexspan']
99 self.linespan = linespan
100 self.lexspan = lexspan
101 self.p = p
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100102
103 def __repr__(self):
104 equals = ("{0}={1!r}".format(k, getattr(self, k))
105 for k in self._fields)
106 args = ", ".join(equals)
107 return "{0}({1})".format(self.__class__.__name__, args)
108
109 def __eq__(self, other):
110 try:
111 return self.__dict__ == other.__dict__
112 except AttributeError:
113 return False
114
115 def __ne__(self, other):
116 return not self == other
117
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100118 def setLexData(self, linespan, lexspan):
119 self.linespan = linespan
120 self.lexspan = lexspan
121
122 def setLexObj(self, p):
123 self.p = p
124
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100125 def accept(self, visitor):
126 pass
127
Dusan Klinece26bb022014-11-09 12:21:37 +0100128class PackageStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100129 def __init__(self, name, linespan=None, lexspan=None, p=None):
130 super(PackageStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
131 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100132 self.name = name
133
134 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100135 visitor.visit_PackageStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100136
137class ImportStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100138 def __init__(self, name, linespan=None, lexspan=None, p=None):
139 super(ImportStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
140 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100141 self.name = name
142
143 def accept(self, visitor):
144 visitor.visit_ImportStatement(self)
145
Dusan Klinece26bb022014-11-09 12:21:37 +0100146class OptionStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100147 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
148 super(OptionStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
149 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100150 self.name = name
151 self.value = value
152
153 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100154 visitor.visit_OptionStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100155
Dusan Klinece26bb022014-11-09 12:21:37 +0100156class FieldDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100157 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
158 super(FieldDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
159 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100160 self.name = name
161 self.value = value
162
163 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100164 if visitor.visit_FieldDirective(self):
165 self.v(self.name, visitor)
166 self.v(self.value, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100167
Dusan Klinece26bb022014-11-09 12:21:37 +0100168class FieldType(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100169 def __init__(self, name, linespan=None, lexspan=None, p=None):
170 super(FieldType, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
171 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100172 self.name = name
173
174 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100175 if visitor.visit_FieldType(self):
176 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100177
Dusan Klinece26bb022014-11-09 12:21:37 +0100178class FieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100179 def __init__(self, field_modifier, ftype, name, fieldId, fieldDirective, linespan=None, lexspan=None, p=None):
180 super(FieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
181 self._fields += ['field_modifier', 'ftype', 'name', 'fieldId', 'fieldDirective']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100182 self.name = name
183 self.field_modifier = field_modifier
184 self.ftype = ftype
185 self.fieldId = fieldId
186 self.fieldDirective = fieldDirective
187
188 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100189 if visitor.visit_FieldDefinition(self):
190 self.v(self.name, visitor)
191 self.v(self.field_modifier, visitor)
192 self.v(self.ftype, visitor)
193 self.v(self.fieldId, visitor)
194 for s in self.fieldDirective:
195 self.v(s, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100196
Dusan Klinece26bb022014-11-09 12:21:37 +0100197class EnumFieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100198 def __init__(self, name, fieldId, linespan=None, lexspan=None, p=None):
199 super(EnumFieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
200 self._fields += ['name', 'fieldId']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100201 self.name = name
202 self.fieldId = fieldId
203
204 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100205 if visitor.visit_EnumFieldDefinition(self):
206 self.v(self.name, visitor)
207 self.v(self.fieldId, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100208
Dusan Klinece26bb022014-11-09 12:21:37 +0100209class EnumDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100210 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
211 super(EnumDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
212 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100213 self.name = name
214 self.body = body
215
216 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100217 if visitor.visit_EnumDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100218 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100219 for s in self.body:
220 s.accept(visitor)
221
Dusan Klinece26bb022014-11-09 12:21:37 +0100222class MessageDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100223 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
224 super(MessageDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
225 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100226 self.name = name
227 self.body = body
228
229 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100230 if visitor.visit_MessageDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100231 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100232 for s in self.body:
233 s.accept(visitor)
234
235class MessageExtension(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100236 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
237 super(MessageExtension, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
238 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100239 self.name = name
240 self.body = body
241
242 def accept(self, visitor):
243 if visitor.visit_MessageExtension(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100244 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100245 for s in self.body:
246 s.accept(visitor)
247
248class MethodDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100249 def __init__(self, name, name2, name3, linespan=None, lexspan=None, p=None):
250 super(MethodDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
251 self._fields += ['name', 'name2', 'name3']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100252 self.name = name
253 self.name2 = name2
254 self.name3 = name3
255
256 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100257 if visitor.visit_MethodDefinition(self):
258 self.v(self.name, visitor)
259 self.v(self.name2, visitor)
260 self.v(self.name3, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100261
Dusan Klinece26bb022014-11-09 12:21:37 +0100262class ServiceDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100263 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
264 super(ServiceDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
265 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100266 self.name = name
267 self.body = body
268
269 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100270 if visitor.visit_ServiceDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100271 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100272 for s in self.body:
273 s.accept(visitor)
274
275class ExtensionsMax(SourceElement):
276 pass
277
278class ExtensionsDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100279 def __init__(self, fromVal, toVal, linespan=None, lexspan=None, p=None):
280 super(ExtensionsDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
281 self._fields += ['fromVal', 'toVal']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100282 self.fromVal = fromVal
283 self.toVal = toVal
284
285 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100286 if visitor.visit_ExtensionsDirective(self):
287 self.v(self.fromVal, visitor)
288 self.v(self.toVal, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100289
290class Literal(SourceElement):
291
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100292 def __init__(self, value, linespan=None, lexspan=None, p=None):
293 super(Literal, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
294 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100295 self.value = value
296
297 def accept(self, visitor):
298 visitor.visit_Literal(self)
299
300class Name(SourceElement):
301
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100302 def __init__(self, value, linespan=None, lexspan=None, p=None):
303 super(Name, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
304 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100305 self.value = value
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100306 self.deriveLex()
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100307
308 def append_name(self, name):
309 try:
310 self.value = self.value + '.' + name.value
311 except:
312 self.value = self.value + '.' + name
313
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100314 def deriveLex(self):
315 if hasattr(self.value, "lexspan"):
316 self.lexspan = self.value.lexspan
317 self.linespan = self.value.linespan
318 else:
319 return
320
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100321 def accept(self, visitor):
322 visitor.visit_Name(self)
323
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100324class DotName(Name):
325 elements = []
326 def __init__(self, elements, linespan=None, lexspan=None, p=None):
327 super(DotName, self).__init__('.'.join([str(x) for x in elements]), linespan=linespan, lexspan=lexspan, p=p)
328 self._fields += ['elements']
329 self.elements = elements
330 self.deriveLex()
331
332 def deriveLex(self):
333 if isinstance(self.elements, list) and len(self.elements)>0:
334 self.lexspan = (min([x.lexspan[0] for x in self.elements if x.lexspan[0] != 0]), max([x.lexspan[1] for x in self.elements if x.lexspan[1] != 0]))
335 self.linespan = (min([x.linespan[0] for x in self.elements if x.linespan[0] != 0]), max([x.linespan[1] for x in self.elements if x.linespan[1] != 0]))
336 elif hasattr(self.elements, "lexspan"):
337 self.lexspan = self.elements.lexspan
338 self.linespan = self.elements.linespan
339 else:
340 return
341
342 def accept(self, visitor):
343 visitor.visit_DotName(self)
344
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100345class ProtoFile(SourceElement):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100346
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100347 def __init__(self, pkg, body, linespan=None, lexspan=None, p=None):
348 super(ProtoFile, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
349 self._fields += ['pkg', 'body']
350 self.pkg = pkg
351 self.body = body
352
353 def accept(self, visitor):
354 if visitor.visit_Proto(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100355 self.v(self.pkg, visitor)
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100356 for s in self.body:
357 s.accept(visitor)