)  # byte is actually only used in byteVec, which is overriden with a special case
p_byte.setParseAction(int)

p_bool = pp.Literal('0') ^ pp.Literal('1')
p_bool.setParseAction(lambda x: bool(x[0]))

p_float = pp.Word(pp.nums + '.eE+-naninfNANINF')
p_float.setParseAction(lambda x: float(x[0]))

p_str = pp.Optional(pp.Word(hexchars))
p_str.setParseAction(lambda x: base64.b16decode(x[0]) if len(x) else '')

# External Type Forward Declarations

# Forward declarations
p_floatYPR = pp.Forward()
p_TimeStamp = pp.Forward()
p_PolarImage = pp.Forward()

p_int32Vec = pp.Forward()
p_byteVec = pp.Forward()

p_ImageEncodingType = pp.Forward()
p_SonarID = pp.Forward()

# Parse Structs
p_floatYPR << pp.Group(l \
    + p_float + c \
    + p_float + c \
    + p_float \
    + r)
p_int.setParseAction(lambda x: int(''.join(x)))


p_byte = pp.Word(hexchars, exact=2) # byte is actually only used in byteVec, which is overriden with a special case
p_byte.setParseAction(int)

p_bool = pp.Literal('0') ^ pp.Literal('1')
p_bool.setParseAction(lambda x: bool(x[0]))

p_float = pp.Word(pp.nums + '.eE+-naninfNANINF')
p_float.setParseAction(lambda x: float(x[0]))

p_str = pp.Optional(pp.Word(hexchars))
p_str.setParseAction(lambda x: base64.b16decode(x[0]) if len(x) else '')

p_Image = pp.Forward()

# Forward declarations
p_floatYPR = pp.Forward()
p_floatXYZ = pp.Forward()
p_floatXY = pp.Forward()
p_NodeInput = pp.Forward()
p_LocalNodeInput = pp.Forward()
p_NodeOutput = pp.Forward()
p_LocalNodeOutput = pp.Forward()
p_NodeInputArc = pp.Forward()
p_NodeOutputArc = pp.Forward()
p_TimeStamp = pp.Forward()
p_SonarDataLine = pp.Forward()
            
p_PolarImage = pp.Forward()
p_byte = pp.Word(hexchars, exact=2) # byte is actually only used in byteVec, which is overriden with a special case
p_byte.setParseAction(int)

p_bool = pp.Literal('0') ^ pp.Literal('1')
p_bool.setParseAction(lambda x: bool(x[0]))

p_float = pp.Word(pp.nums + '.eE+-naninfNANINF')
p_float.setParseAction(lambda x: float(x[0]))

p_str = pp.Optional(pp.Word(hexchars))
p_str.setParseAction(lambda x: base64.b16decode(x[0]) if len(x) else '')

# External Type Forward Declarations
# TODO: autogenerate these
p_Image = pp.Forward()
p_BoundedFloat = pp.Forward()

# Forward declarations
p_floatYPR = pp.Forward()
p_floatXYZ = pp.Forward()
p_floatXY = pp.Forward()
p_NodeInput = pp.Forward()
p_LocalNodeInput = pp.Forward()
            
p_NodeOutput = pp.Forward()
p_LocalNodeOutput = pp.Forward()
p_NodeInputArc = pp.Forward()
p_NodeOutputArc = pp.Forward()
p_TimeStamp = pp.Forward()
p_SonarDataLine = pp.Forward()