# Basic Types
# being less strict in parsing here leads to much simpler (=faster) parsing!
p_int = pp.Word(pp.nums + '+-')
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()
# being less strict in parsing here leads to much simpler (=faster) parsing!
p_int = pp.Word(pp.nums + '+-')
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 '')

# 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()