def parse_functions(self, src): """Updates self.funcs_dict.""" parser = header_parsing.MJAPI_FUNCTION_DECL for tokens, _, _ in parser.scanString(src): for token in tokens: name = codegen_util.mangle_varname(token.name) comment = codegen_util.mangle_comment(token.comment) args = codegen_util.UniqueOrderedDict() for arg in token.arguments: a = self.get_type_from_token(arg) args[a.name] = a r = self.get_type_from_token(token.return_value) f = c_declarations.Function(name, args, r, comment) self.funcs_dict[f.name] = f
def get_type_from_token(self, token, parent=None): """Accepts a token returned by a parser, returns a subclass of CDeclBase.""" comment = codegen_util.mangle_comment(token.comment) is_const = token.is_const == "const" # A new struct declaration if token.members: name = token.name # If the name is empty, see if there is a type declaration that matches # this struct's typename if not name: for k, v in six.iteritems(self.typedefs_dict): if v == token.typename: name = k # Anonymous structs need a dummy typename typename = token.typename if not typename: if parent: typename = token.name else: raise Error( "Anonymous structs that aren't members of a named struct are not " "supported (name = '{token.name}').".format( token=token)) # Mangle the name if it contains any protected keywords name = codegen_util.mangle_varname(name) members = codegen_util.UniqueOrderedDict() sub_structs = codegen_util.UniqueOrderedDict() out = c_declarations.Struct(name, typename, members, sub_structs, comment, parent, is_const) # Map the old typename to the mangled typename in typedefs_dict self.typedefs_dict[typename] = out.ctypes_typename # Add members for sub_token in token.members: # Recurse into nested structs member = self.get_type_from_token(sub_token, parent=out) out.members[member.name] = member # Nested sub-structures need special treatment if isinstance(member, c_declarations.Struct): out.sub_structs[member.name] = member # Add to dict of structs self.structs_dict[out.ctypes_typename] = out else: name = codegen_util.mangle_varname(token.name) typename = self.resolve_typename(token.typename) # 1D array with size defined at compile time if token.size: shape = self.get_shape_tuple(token.size) if typename in header_parsing.CTYPES_TO_NUMPY: out = c_declarations.StaticNDArray(name, typename, shape, comment, parent, is_const) else: out = c_declarations.StaticPtrArray( name, typename, shape, comment, parent, is_const) elif token.ptr: # Pointer to a numpy-compatible type, could be an array or a scalar if typename in header_parsing.CTYPES_TO_NUMPY: # Multidimensional array (one or more dimensions might be undefined) if name in self.hints_dict: # Dynamically-sized dimensions have string identifiers shape = self.hints_dict[name] if any(isinstance(d, str) for d in shape): out = c_declarations.DynamicNDArray( name, typename, shape, comment, parent, is_const) else: out = c_declarations.StaticNDArray( name, typename, shape, comment, parent, is_const) # This must be a pointer to a scalar primitive else: out = c_declarations.ScalarPrimitivePtr( name, typename, comment, parent, is_const) # Pointer to struct or other arbitrary type else: out = c_declarations.ScalarPrimitivePtr( name, typename, comment, parent, is_const) # A struct we've already encountered elif typename in self.structs_dict: s = self.structs_dict[typename] out = c_declarations.Struct(name, s.typename, s.members, s.sub_structs, comment, parent) # Presumably this is a scalar primitive else: out = c_declarations.ScalarPrimitive(name, typename, comment, parent, is_const) return out