blob: 5369fde333635aeb8a645f001442e427feb9a24f [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
Dusan Klinec00eb5da2014-11-10 21:24:15 +010042 lexspan = None
43 linespan = None
Dusan Klineca9f6d362014-11-10 21:07:08 +010044
45 def v(self, obj, visitor):
46 if obj == None:
47 return
48 if not hasattr(obj, "accept"):
49 return
50 obj.accept(visitor)
Dusan Klinece26bb022014-11-09 12:21:37 +010051
Dusan Klinecaa9ff472014-11-10 18:02:03 +010052# Lexical unit - contains lexspan and linespan for later analysis.
Dusan Klineca9f6d362014-11-10 21:07:08 +010053class LU(Base):
Dusan Klinecaa9ff472014-11-10 18:02:03 +010054 def __init__(self, p, idx):
55 self.p = p
56 self.idx = idx
57 self.pval = p[idx]
58 self.lexspan = p.lexspan(idx)
59 self.linespan = p.linespan(idx)
60
61 # If string is in the value (raw value) and start and stop lexspan is the same, add real span
62 # obtained by string length.
63 if isinstance(self.pval, str) \
64 and self.lexspan != None \
65 and self.lexspan[0] == self.lexspan[1] \
66 and self.lexspan[0] != 0:
67 self.lexspan = tuple([self.lexspan[0], self.lexspan[0] + len(self.pval)])
68 super(LU, self).__init__()
69
70 @staticmethod
71 def i(p, idx):
72 if isinstance(p[idx], LU): return p[idx]
73 if isinstance(p[idx], str): return LU(p, idx)
74 return p[idx]
75
76 def describe(self):
77 return "LU(%s,%s)" % (self.pval, self.lexspan)
78
79 def __str__(self):
80 return self.pval
81
82 def __repr__(self):
83 return self.describe()
84
85 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +010086 self.v(self.pval, visitor)
Dusan Klinecaa9ff472014-11-10 18:02:03 +010087
88 def __iter__(self):
89 for x in self.pval:
90 yield x
91
Dusan Klinecccaa0d92014-11-09 03:21:31 +010092# Base node
Dusan Klineca9f6d362014-11-10 21:07:08 +010093class SourceElement(Base):
Dusan Klinecccaa0d92014-11-09 03:21:31 +010094 '''
Dusan Klinece26bb022014-11-09 12:21:37 +010095 A SourceElement is the base class for all elements that occur in a Protocol Buffers
96 file parsed by plyproto.
Dusan Klinecccaa0d92014-11-09 03:21:31 +010097 '''
Dusan Klinecc9b031a2014-11-10 13:21:08 +010098 def __init__(self, linespan=[], lexspan=[], p=None):
Dusan Klinecccaa0d92014-11-09 03:21:31 +010099 super(SourceElement, self).__init__()
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100100 self._fields = [] # ['linespan', 'lexspan']
101 self.linespan = linespan
102 self.lexspan = lexspan
103 self.p = p
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100104
105 def __repr__(self):
106 equals = ("{0}={1!r}".format(k, getattr(self, k))
107 for k in self._fields)
108 args = ", ".join(equals)
109 return "{0}({1})".format(self.__class__.__name__, args)
110
111 def __eq__(self, other):
112 try:
113 return self.__dict__ == other.__dict__
114 except AttributeError:
115 return False
116
117 def __ne__(self, other):
118 return not self == other
119
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100120 def setLexData(self, linespan, lexspan):
121 self.linespan = linespan
122 self.lexspan = lexspan
123
124 def setLexObj(self, p):
125 self.p = p
126
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100127 def accept(self, visitor):
128 pass
129
Dusan Klinece26bb022014-11-09 12:21:37 +0100130class PackageStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100131 def __init__(self, name, linespan=None, lexspan=None, p=None):
132 super(PackageStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
133 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100134 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100135 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100136
137 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100138 visitor.visit_PackageStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100139
140class ImportStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100141 def __init__(self, name, linespan=None, lexspan=None, p=None):
142 super(ImportStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
143 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100144 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100145 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100146
147 def accept(self, visitor):
148 visitor.visit_ImportStatement(self)
149
Dusan Klinece26bb022014-11-09 12:21:37 +0100150class OptionStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100151 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
152 super(OptionStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
153 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100154 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100155 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100156 self.value = value
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100157 self.value.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100158
159 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100160 visitor.visit_OptionStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100161
Dusan Klinece26bb022014-11-09 12:21:37 +0100162class FieldDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100163 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
164 super(FieldDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
165 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100166 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100167 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100168 self.value = value
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100169 self.value.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100170
171 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100172 if visitor.visit_FieldDirective(self):
173 self.v(self.name, visitor)
174 self.v(self.value, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100175
Dusan Klinece26bb022014-11-09 12:21:37 +0100176class FieldType(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100177 def __init__(self, name, linespan=None, lexspan=None, p=None):
178 super(FieldType, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
179 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100180 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100181 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100182
183 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100184 if visitor.visit_FieldType(self):
185 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100186
Dusan Klinece26bb022014-11-09 12:21:37 +0100187class FieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100188 def __init__(self, field_modifier, ftype, name, fieldId, fieldDirective, linespan=None, lexspan=None, p=None):
189 super(FieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
190 self._fields += ['field_modifier', 'ftype', 'name', 'fieldId', 'fieldDirective']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100191 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100192 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100193 self.field_modifier = field_modifier
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100194 self.field_modifier.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100195 self.ftype = ftype
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100196 self.ftype.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100197 self.fieldId = fieldId
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100198 self.fieldId.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100199 self.fieldDirective = fieldDirective
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100200 for s in self.fieldDirective:
201 s.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100202
203 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100204 if visitor.visit_FieldDefinition(self):
205 self.v(self.name, visitor)
206 self.v(self.field_modifier, visitor)
207 self.v(self.ftype, visitor)
208 self.v(self.fieldId, visitor)
209 for s in self.fieldDirective:
210 self.v(s, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100211
Dusan Klinece26bb022014-11-09 12:21:37 +0100212class EnumFieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100213 def __init__(self, name, fieldId, linespan=None, lexspan=None, p=None):
214 super(EnumFieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
215 self._fields += ['name', 'fieldId']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100216 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100217 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100218 self.fieldId = fieldId
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100219 self.fieldId.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100220
221 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100222 if visitor.visit_EnumFieldDefinition(self):
223 self.v(self.name, visitor)
224 self.v(self.fieldId, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100225
Dusan Klinece26bb022014-11-09 12:21:37 +0100226class EnumDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100227 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
228 super(EnumDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
229 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100230 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100231 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100232 self.body = body
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100233 for s in self.body:
234 s.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100235
236 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100237 if visitor.visit_EnumDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100238 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100239 for s in self.body:
240 s.accept(visitor)
241
Dusan Klinece26bb022014-11-09 12:21:37 +0100242class MessageDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100243 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
244 super(MessageDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
245 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100246 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100247 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100248 self.body = body
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100249 for s in self.body:
250 s.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100251
252 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100253 if visitor.visit_MessageDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100254 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100255 for s in self.body:
256 s.accept(visitor)
257
258class MessageExtension(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100259 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
260 super(MessageExtension, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
261 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100262 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100263 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100264 self.body = body
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100265 for s in self.body:
266 s.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100267
268 def accept(self, visitor):
269 if visitor.visit_MessageExtension(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100270 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100271 for s in self.body:
272 s.accept(visitor)
273
274class MethodDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100275 def __init__(self, name, name2, name3, linespan=None, lexspan=None, p=None):
276 super(MethodDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
277 self._fields += ['name', 'name2', 'name3']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100278 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100279 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100280 self.name2 = name2
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100281 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100282 self.name3 = name3
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100283 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100284
285 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100286 if visitor.visit_MethodDefinition(self):
287 self.v(self.name, visitor)
288 self.v(self.name2, visitor)
289 self.v(self.name3, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100290
Dusan Klinece26bb022014-11-09 12:21:37 +0100291class ServiceDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100292 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
293 super(ServiceDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
294 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100295 self.name = name
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100296 self.name.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100297 self.body = body
298
299 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100300 if visitor.visit_ServiceDefinition(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100301 self.v(self.name, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100302 for s in self.body:
303 s.accept(visitor)
304
305class ExtensionsMax(SourceElement):
306 pass
307
308class ExtensionsDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100309 def __init__(self, fromVal, toVal, linespan=None, lexspan=None, p=None):
310 super(ExtensionsDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
311 self._fields += ['fromVal', 'toVal']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100312 self.fromVal = fromVal
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100313 self.fromVal.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100314 self.toVal = toVal
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100315 self.toVal.parent = self
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100316
317 def accept(self, visitor):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100318 if visitor.visit_ExtensionsDirective(self):
319 self.v(self.fromVal, visitor)
320 self.v(self.toVal, visitor)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100321
322class Literal(SourceElement):
323
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100324 def __init__(self, value, linespan=None, lexspan=None, p=None):
325 super(Literal, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
326 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100327 self.value = value
328
329 def accept(self, visitor):
330 visitor.visit_Literal(self)
331
332class Name(SourceElement):
333
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100334 def __init__(self, value, linespan=None, lexspan=None, p=None):
335 super(Name, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
336 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100337 self.value = value
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100338 self.deriveLex()
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100339
340 def append_name(self, name):
341 try:
342 self.value = self.value + '.' + name.value
343 except:
344 self.value = self.value + '.' + name
345
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100346 def deriveLex(self):
347 if hasattr(self.value, "lexspan"):
348 self.lexspan = self.value.lexspan
349 self.linespan = self.value.linespan
350 else:
351 return
352
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100353 def accept(self, visitor):
354 visitor.visit_Name(self)
355
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100356class DotName(Name):
357 elements = []
358 def __init__(self, elements, linespan=None, lexspan=None, p=None):
359 super(DotName, self).__init__('.'.join([str(x) for x in elements]), linespan=linespan, lexspan=lexspan, p=p)
360 self._fields += ['elements']
361 self.elements = elements
362 self.deriveLex()
363
364 def deriveLex(self):
365 if isinstance(self.elements, list) and len(self.elements)>0:
366 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]))
367 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]))
368 elif hasattr(self.elements, "lexspan"):
369 self.lexspan = self.elements.lexspan
370 self.linespan = self.elements.linespan
371 else:
372 return
373
374 def accept(self, visitor):
375 visitor.visit_DotName(self)
376
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100377class ProtoFile(SourceElement):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100378
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100379 def __init__(self, pkg, body, linespan=None, lexspan=None, p=None):
380 super(ProtoFile, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
381 self._fields += ['pkg', 'body']
382 self.pkg = pkg
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100383 self.pkg.parent = self
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100384 self.body = body
Dusan Klinec00eb5da2014-11-10 21:24:15 +0100385 for s in self.body:
386 s.parent = self
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100387
388 def accept(self, visitor):
389 if visitor.visit_Proto(self):
Dusan Klineca9f6d362014-11-10 21:07:08 +0100390 self.v(self.pkg, visitor)
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100391 for s in self.body:
392 s.accept(visitor)