I have a small program which makes uses of pycparser to parse C header files. The code, unfortunately, kinda sprawls out everywhere to handle the different cases (example below).
What's the best way to make this more Pythonic? I thought about case-statements, but those don't exist in Python. Is splitting the function into smaller functions the best approach?
def build_struct(decl):
""" Recursively builds a structure from external definition.
"""
_type = type(decl)
if _type == TypeDecl:
return build_struct(decl.type)
elif _type == IdentifierType:
return " ".join(decl.names)
elif _type == ID:
return ['ID', decl.name]
elif _type == Struct:
struct = c_types.structureDefinition()
for d in decl.decls:
field = build_struct(d)
struct.add_field(field)
return struct
elif _type == Union:
union = c_types.unionDefinition()
for d in decl.decls:
field = build_struct(d)
union.add_field(field)
return union
elif _type == Enum:
# not implemented yet... but don't raise an exception
# unsure if there is any value in supporting enums
return
else:
nested = build_struct(decl.type)
if _type == Decl:
if decl.bitsize:
# fields with bitsize defined (i.e. valid:1)
return c_types.fieldDefinition(decl.name,
int(decl.bitsize.value))
elif isinstance(nested, c_types.structureDefinition):
# if it's a structure, assign it's name
nested.name = decl.name
return nested
elif isinstance(nested, c_types.unionDefinition):
# if it's a union, assign it's name
nested.name = decl.name
return nested
elif isinstance(nested, int):
# if it's an array, we will just return the total size
return c_types.fieldDefinition(decl.name, nested)
else:
# fields w/o bitsized defined
id = nested
# using defined types, like uint32_t
if id in c_types.size_d:
size = c_types.size_d[id]
# using defined structures, like fast_ip
elif id in c_types.structs:
return c_types.structs[id]
else:
raise c_types.UnknownIdentifier(id)
# regular fields, i.e. int count;
return c_types.fieldDefinition(decl.name, int(size))
elif _type == Typename: # for function parameters
raise c_types.NotImplemented
elif _type == ArrayDecl:
#raise c_types.NotImplemented
dimval = decl.dim.value if decl.dim else ''
id = nested
# using defined types, like uint32_t
if id in c_types.size_d:
size = c_types.size_d[id]
# using defined structures, like fast_ip
elif id in c_types.structs:
return c_types.structs[id]
else:
raise c_types.UnknownIdentifier(id)
return int(dimval) * size
elif _type == PtrDecl:
raise c_types.NotImplemented
elif _type == Typedef:
id = nested
# TODO -- this is very common... refactor
if isinstance(id, c_types.structureDefinition):
# typedef struct ...
# TODO -- very similar to code above...
id.name = decl.name
return id
if isinstance(id, c_types.unionDefinition):
# typedef struct ...
# TODO -- very similar to code above...
id.name = decl.name
return id
# TODO -- change to c_types.fieldDefinition
# TODO -- this is very common... refactor
if id in c_types.size_d:
# typdef uint32 unsigned long;
c_types.size_d[decl.name] = c_types.size_d[id]
return c_types.size_d[decl.name]
elif id in c_types.structs:
return c_types.structs[id]
elif not id:
# unhandled cases, like enum
return
else:
raise c_types.UnknownIdentifier(id)
elif _type == FuncDecl:
raise c_types.NotImplementede