blob: 2cfc4c3e764c1ca8370f601efa24ca59632bab80 [file] [log] [blame]
class LexHelper:
offset = 0
def get_max_linespan(self, p):
defSpan = [1e60, -1]
mSpan = [1e60, -1]
for sp in range(0, len(p)):
csp = p.linespan(sp)
if csp[0] == 0 and csp[1] == 0:
if hasattr(p[sp], "linespan"):
csp = p[sp].linespan
else:
continue
if csp is None or len(csp) != 2:
continue
if csp[0] == 0 and csp[1] == 0:
continue
if csp[0] < mSpan[0]:
mSpan[0] = csp[0]
if csp[1] > mSpan[1]:
mSpan[1] = csp[1]
if defSpan == mSpan:
return (0, 0)
return tuple([mSpan[0] - self.offset, mSpan[1] - self.offset])
def get_max_lexspan(self, p):
defSpan = [1e60, -1]
mSpan = [1e60, -1]
for sp in range(0, len(p)):
csp = p.lexspan(sp)
if csp[0] == 0 and csp[1] == 0:
if hasattr(p[sp], "lexspan"):
csp = p[sp].lexspan
else:
continue
if csp is None or len(csp) != 2:
continue
if csp[0] == 0 and csp[1] == 0:
continue
if csp[0] < mSpan[0]:
mSpan[0] = csp[0]
if csp[1] > mSpan[1]:
mSpan[1] = csp[1]
if defSpan == mSpan:
return (0, 0)
return tuple([mSpan[0] - self.offset, mSpan[1] - self.offset])
def set_parse_object(self, dst, p):
dst.setLexData(
linespan=self.get_max_linespan(p),
lexspan=self.get_max_lexspan(p))
dst.setLexObj(p)
class Base(object):
parent = None
lexspan = None
linespan = None
def v(self, obj, visitor):
if obj is None:
return
elif hasattr(obj, "accept"):
obj.accept(visitor)
elif isinstance(obj, list):
for s in obj:
self.v(s, visitor)
pass
pass
@staticmethod
def p(obj, parent):
if isinstance(obj, list):
for s in obj:
Base.p(s, parent)
if hasattr(obj, "parent"):
obj.parent = parent
# Lexical unit - contains lexspan and linespan for later analysis.
class LU(Base):
def __init__(self, p, idx):
self.p = p
self.idx = idx
self.pval = p[idx]
self.lexspan = p.lexspan(idx)
self.linespan = p.linespan(idx)
# If string is in the value (raw value) and start and stop lexspan is the same, add real span
# obtained by string length.
if isinstance(self.pval, str) \
and self.lexspan is not None \
and self.lexspan[0] == self.lexspan[1] \
and self.lexspan[0] != 0:
self.lexspan = tuple(
[self.lexspan[0], self.lexspan[0] + len(self.pval)])
super(LU, self).__init__()
@staticmethod
def i(p, idx):
if isinstance(p[idx], LU):
return p[idx]
if isinstance(p[idx], str):
return LU(p, idx)
return p[idx]
def describe(self):
return "LU(%s,%s)" % (self.pval, self.lexspan)
def __str__(self):
return self.pval
def __repr__(self):
return self.describe()
def accept(self, visitor):
self.v(self.pval, visitor)
def __iter__(self):
for x in self.pval:
yield x
# Base node
class SourceElement(Base):
'''
A SourceElement is the base class for all elements that occur in a Protocol Buffers
file parsed by plyproto.
'''
def __init__(self, linespan=[], lexspan=[], p=None):
super(SourceElement, self).__init__()
self._fields = [] # ['linespan', 'lexspan']
self.linespan = linespan
self.lexspan = lexspan
self.p = p
def __repr__(self):
equals = ("{0}={1!r}".format(k, getattr(self, k))
for k in self._fields)
args = ", ".join(equals)
return "{0}({1})".format(self.__class__.__name__, args)
def __eq__(self, other):
try:
return self.__dict__ == other.__dict__
except AttributeError:
return False
def __ne__(self, other):
return not self == other
def setLexData(self, linespan, lexspan):
self.linespan = linespan
self.lexspan = lexspan
def setLexObj(self, p):
self.p = p
def accept(self, visitor):
pass
class Visitor(object):
def __init__(self, verbose=False):
self.verbose = verbose
def __getattr__(self, name):
if not name.startswith('visit_'):
raise AttributeError(
'name must start with visit_ but was {}'.format(name))
def f(element):
if self.verbose:
msg = 'unimplemented call to {}; ignoring ({})'
print(msg.format(name, element))
return True
return f
# visitor.visit_PackageStatement(self)
# visitor.visit_ImportStatement(self)
# visitor.visit_OptionStatement(self)
# visitor.visit_FieldDirective(self)
# visitor.visit_FieldType(self)
# visitor.visit_FieldDefinition(self)
# visitor.visit_EnumFieldDefinition(self)
# visitor.visit_EnumDefinition(self)
# visitor.visit_MessageDefinition(self)
# visitor.visit_MessageExtension(self)
# visitor.visit_MethodDefinition(self)
# visitor.visit_ServiceDefinition(self)
# visitor.visit_ExtensionsDirective(self)
# visitor.visit_Literal(self)
# visitor.visit_Name(self)
# visitor.visit_Proto(self)
# visitor.visit_LU(self)