blob: bcff7ee1abdd2508e9eb2eb0df7426132bded537 [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 Klinece26bb022014-11-09 12:21:37 +010038
Dusan Klinecaa9ff472014-11-10 18:02:03 +010039# Lexical unit - contains lexspan and linespan for later analysis.
40class LU(object):
41 def __init__(self, p, idx):
42 self.p = p
43 self.idx = idx
44 self.pval = p[idx]
45 self.lexspan = p.lexspan(idx)
46 self.linespan = p.linespan(idx)
47
48 # If string is in the value (raw value) and start and stop lexspan is the same, add real span
49 # obtained by string length.
50 if isinstance(self.pval, str) \
51 and self.lexspan != None \
52 and self.lexspan[0] == self.lexspan[1] \
53 and self.lexspan[0] != 0:
54 self.lexspan = tuple([self.lexspan[0], self.lexspan[0] + len(self.pval)])
55 super(LU, self).__init__()
56
57 @staticmethod
58 def i(p, idx):
59 if isinstance(p[idx], LU): return p[idx]
60 if isinstance(p[idx], str): return LU(p, idx)
61 return p[idx]
62
63 def describe(self):
64 return "LU(%s,%s)" % (self.pval, self.lexspan)
65
66 def __str__(self):
67 return self.pval
68
69 def __repr__(self):
70 return self.describe()
71
72 def accept(self, visitor):
73 pass
74
75 def __iter__(self):
76 for x in self.pval:
77 yield x
78
Dusan Klinecccaa0d92014-11-09 03:21:31 +010079# Base node
80class SourceElement(object):
81 '''
Dusan Klinece26bb022014-11-09 12:21:37 +010082 A SourceElement is the base class for all elements that occur in a Protocol Buffers
83 file parsed by plyproto.
Dusan Klinecccaa0d92014-11-09 03:21:31 +010084 '''
Dusan Klinecc9b031a2014-11-10 13:21:08 +010085 def __init__(self, linespan=[], lexspan=[], p=None):
Dusan Klinecccaa0d92014-11-09 03:21:31 +010086 super(SourceElement, self).__init__()
Dusan Klinecc9b031a2014-11-10 13:21:08 +010087 self._fields = [] # ['linespan', 'lexspan']
88 self.linespan = linespan
89 self.lexspan = lexspan
90 self.p = p
Dusan Klinecccaa0d92014-11-09 03:21:31 +010091
92 def __repr__(self):
93 equals = ("{0}={1!r}".format(k, getattr(self, k))
94 for k in self._fields)
95 args = ", ".join(equals)
96 return "{0}({1})".format(self.__class__.__name__, args)
97
98 def __eq__(self, other):
99 try:
100 return self.__dict__ == other.__dict__
101 except AttributeError:
102 return False
103
104 def __ne__(self, other):
105 return not self == other
106
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100107 def setLexData(self, linespan, lexspan):
108 self.linespan = linespan
109 self.lexspan = lexspan
110
111 def setLexObj(self, p):
112 self.p = p
113
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100114 def accept(self, visitor):
115 pass
116
Dusan Klinece26bb022014-11-09 12:21:37 +0100117class PackageStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100118 def __init__(self, name, linespan=None, lexspan=None, p=None):
119 super(PackageStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
120 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100121 self.name = name
122
123 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100124 visitor.visit_PackageStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100125
126class ImportStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100127 def __init__(self, name, linespan=None, lexspan=None, p=None):
128 super(ImportStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
129 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100130 self.name = name
131
132 def accept(self, visitor):
133 visitor.visit_ImportStatement(self)
134
Dusan Klinece26bb022014-11-09 12:21:37 +0100135class OptionStatement(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100136 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
137 super(OptionStatement, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
138 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100139 self.name = name
140 self.value = value
141
142 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100143 visitor.visit_OptionStatement(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100144
Dusan Klinece26bb022014-11-09 12:21:37 +0100145class FieldDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100146 def __init__(self, name, value, linespan=None, lexspan=None, p=None):
147 super(FieldDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
148 self._fields += ['name', 'value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100149 self.name = name
150 self.value = value
151
152 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100153 visitor.visit_FieldDirective(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100154
Dusan Klinece26bb022014-11-09 12:21:37 +0100155class FieldType(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100156 def __init__(self, name, linespan=None, lexspan=None, p=None):
157 super(FieldType, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
158 self._fields += ['name']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100159 self.name = name
160
161 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100162 visitor.visit_FieldType(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100163
Dusan Klinece26bb022014-11-09 12:21:37 +0100164class FieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100165 def __init__(self, field_modifier, ftype, name, fieldId, fieldDirective, linespan=None, lexspan=None, p=None):
166 super(FieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
167 self._fields += ['field_modifier', 'ftype', 'name', 'fieldId', 'fieldDirective']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100168 self.name = name
169 self.field_modifier = field_modifier
170 self.ftype = ftype
171 self.fieldId = fieldId
172 self.fieldDirective = fieldDirective
173
174 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100175 visitor.visit_FieldDefinition(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100176
Dusan Klinece26bb022014-11-09 12:21:37 +0100177class EnumFieldDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100178 def __init__(self, name, fieldId, linespan=None, lexspan=None, p=None):
179 super(EnumFieldDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
180 self._fields += ['name', 'fieldId']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100181 self.name = name
182 self.fieldId = fieldId
183
184 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100185 visitor.visit_EnumFieldDefinition(self)
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100186
Dusan Klinece26bb022014-11-09 12:21:37 +0100187class EnumDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100188 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
189 super(EnumDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
190 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100191 self.name = name
192 self.body = body
193
194 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100195 if visitor.visit_EnumDefinition(self):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100196 for s in self.body:
197 s.accept(visitor)
198
Dusan Klinece26bb022014-11-09 12:21:37 +0100199class MessageDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100200 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
201 super(MessageDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
202 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100203 self.name = name
204 self.body = body
205
206 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100207 if visitor.visit_MessageDefinition(self):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100208 for s in self.body:
209 s.accept(visitor)
210
211class MessageExtension(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100212 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
213 super(MessageExtension, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
214 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100215 self.name = name
216 self.body = body
217
218 def accept(self, visitor):
219 if visitor.visit_MessageExtension(self):
220 for s in self.body:
221 s.accept(visitor)
222
223class MethodDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100224 def __init__(self, name, name2, name3, linespan=None, lexspan=None, p=None):
225 super(MethodDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
226 self._fields += ['name', 'name2', 'name3']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100227 self.name = name
228 self.name2 = name2
229 self.name3 = name3
230
231 def accept(self, visitor):
232 visitor.visit_MethodDefinition(self)
233
Dusan Klinece26bb022014-11-09 12:21:37 +0100234class ServiceDefinition(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100235 def __init__(self, name, body, linespan=None, lexspan=None, p=None):
236 super(ServiceDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
237 self._fields += ['name', 'body']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100238 self.name = name
239 self.body = body
240
241 def accept(self, visitor):
Dusan Klinece26bb022014-11-09 12:21:37 +0100242 if visitor.visit_ServiceDefinition(self):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100243 for s in self.body:
244 s.accept(visitor)
245
246class ExtensionsMax(SourceElement):
247 pass
248
249class ExtensionsDirective(SourceElement):
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100250 def __init__(self, fromVal, toVal, linespan=None, lexspan=None, p=None):
251 super(ExtensionsDirective, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
252 self._fields += ['fromVal', 'toVal']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100253 self.fromVal = fromVal
254 self.toVal = toVal
255
256 def accept(self, visitor):
257 visitor.visit_ExtensionsDirective(self)
258
259class Literal(SourceElement):
260
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100261 def __init__(self, value, linespan=None, lexspan=None, p=None):
262 super(Literal, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
263 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100264 self.value = value
265
266 def accept(self, visitor):
267 visitor.visit_Literal(self)
268
269class Name(SourceElement):
270
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100271 def __init__(self, value, linespan=None, lexspan=None, p=None):
272 super(Name, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
273 self._fields += ['value']
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100274 self.value = value
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100275 self.deriveLex()
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100276
277 def append_name(self, name):
278 try:
279 self.value = self.value + '.' + name.value
280 except:
281 self.value = self.value + '.' + name
282
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100283 def deriveLex(self):
284 if hasattr(self.value, "lexspan"):
285 self.lexspan = self.value.lexspan
286 self.linespan = self.value.linespan
287 else:
288 return
289
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100290 def accept(self, visitor):
291 visitor.visit_Name(self)
292
Dusan Klinecaa9ff472014-11-10 18:02:03 +0100293class DotName(Name):
294 elements = []
295 def __init__(self, elements, linespan=None, lexspan=None, p=None):
296 super(DotName, self).__init__('.'.join([str(x) for x in elements]), linespan=linespan, lexspan=lexspan, p=p)
297 self._fields += ['elements']
298 self.elements = elements
299 self.deriveLex()
300
301 def deriveLex(self):
302 if isinstance(self.elements, list) and len(self.elements)>0:
303 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]))
304 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]))
305 elif hasattr(self.elements, "lexspan"):
306 self.lexspan = self.elements.lexspan
307 self.linespan = self.elements.linespan
308 else:
309 return
310
311 def accept(self, visitor):
312 visitor.visit_DotName(self)
313
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100314class ProtoFile(SourceElement):
Dusan Klinecccaa0d92014-11-09 03:21:31 +0100315
Dusan Klinecc9b031a2014-11-10 13:21:08 +0100316 def __init__(self, pkg, body, linespan=None, lexspan=None, p=None):
317 super(ProtoFile, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
318 self._fields += ['pkg', 'body']
319 self.pkg = pkg
320 self.body = body
321
322 def accept(self, visitor):
323 if visitor.visit_Proto(self):
324 for s in self.body:
325 s.accept(visitor)