WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_PARSE_DECLARATION_C
#define WONKY_PARSE_DECLARATION_C WONKY_PARSE_DECLARATION_C
#include <parse_declaration.h>

#warning main(){return 0;} segfaults wonky
/*declaration-specifiers init-declarator (,init-declarator)* ;*/
/* init-declarator: declarator [ = initializer ] */
void parse_declaration_inner(struct Translation_Data *translation_data,struct Scope *scope,struct Queue *where_to_push_objects,struct Queue *where_to_push_function_definitions,_Bool parse_function_definitions)
{
	struct Denotation_Prototype *prototype;
	struct Denoted *hold;

	prototype=parse_declaration_specifiers(translation_data,scope);

	while(!get_and_check(translation_data,KW_SEMICOLON))
	{
		hold=parse_declarator(translation_data,scope,prototype);
		if(hold->denotation==DT_Function)
		{
			//Scope_Push(scope,hold,translation_data);
			/*check if this is a function definition*/
			if(parse_function_definitions && get_and_check(translation_data,KW_OPEN_CURLY))
			{
				parse_finish_function_definition(translation_data,scope,(struct Denoted_Function*)hold,where_to_push_function_definitions);
				break; /*leave the declarator parser loop*/
			}else
			{
				Scope_Push(scope,hold,translation_data);
				resolve_function_linkage(scope,translation_data,(struct Denoted_Function*)hold);
				push_function_declaration_into_linkage(translation_data,get_function_declaration_tree(scope,(struct Denoted_Function*)hold));
			}
		}else if(hold->denotation==DT_Object)
		{
			parse_finish_object_declaration(translation_data,scope,(struct Denoted_Object*)hold,where_to_push_objects);
		}else if(hold->denotation==DT_Typedef)
		{
			Scope_Push(scope,hold,translation_data);
		}else
		{
			/*TODO error*/
			Queue_Push(where_to_push_objects,get_declaration_error_tree(hold));
			push_translation_error("declaration expected",translation_data);

			/*search for end of erronous declaration*/
			break;
		}

		wonky_assert(is_valid_denoted(hold));

		parse_function_definitions=0; /*here so we don't have int a,main(){ return 0 }*/

		if(!get_and_check(translation_data,KW_COMMA) && !check(translation_data,KW_SEMICOLON))
		{
			/*TODO error*/
			Queue_Push(where_to_push_objects,get_declaration_error_tree(NULL));
			push_translation_error("Semicolon expected",translation_data);
			break;
		}
	}

	wonky_free(prototype);

}

void parse_external_definition(struct Translation_Data *translation_data,struct AST_Translation_Unit *unit)
{
	parse_declaration_inner(translation_data,unit->file_scope,unit->object_declarations,unit->function_definitions,1);
}
void parse_declaration(struct Translation_Data *translation_data,struct Scope *scope,struct Queue *where_to_push_declarations)
{
	parse_declaration_inner(translation_data,scope,where_to_push_declarations,where_to_push_declarations,0);
}
void parse_finish_function_definition(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Function *function,struct Queue *where_to_push)
{
	struct Type_Function *function_type;
	struct AST_Compound_Statement *function_body;
	struct AST_Function_Definition *function_definition;

	function_type=(struct Type_Function*)function->type;
	

	function->function_scope=(struct Function_Scope*)get_function_scope(scope,function);

	function_type->function_prototype_scope->parent=(struct Scope*)function->function_scope;

	wonky_assert(is_valid_denoted_function(function) && is_valid_type((struct Type*)function_type));

	resolve_function_linkage(scope,translation_data,function);
	Scope_Push(scope,(struct Denoted*)function,translation_data);

	function_body
		=
		(struct AST_Compound_Statement*)
		parse_finish_compound_statement(
						translation_data,
						(struct Scope*)function_type->function_prototype_scope,
						&(struct Parse_Statement_Data)
						{
							.break_statement_owner=NULL,
							.continue_statement_owner=NULL,
							.current_switch_statement=NULL,	
						}
					);

	wonky_assert(is_valid_compound_statement(function_body));


	function_definition=get_function_definition_tree(scope,function,function_body,translation_data);

	push_function_definition_into_linkage(translation_data,function_definition);
	Queue_Push(where_to_push,function_definition);
}
void parse_finish_object_declaration(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Object *object,struct Queue *where_to_push)
{
	struct Initialiser *initializer=NULL;
	struct AST_Expression *to_be_initialised;
	struct AST_Object_Declaration *object_declaration;

	to_be_initialised=(struct AST_Expression*)get_designator_tree_from_denoted_object(object,translation_data);
	if(get_and_check(translation_data,KW_EQ))
	{
		initializer=parse_initialiser(translation_data,scope,object->object->type);
		wonky_assert(is_valid_initialiser(initializer));
	}


	object_declaration=get_object_declaration_tree(object,initializer);

	resolve_object_linkage(scope,translation_data,object);

	Scope_Push(scope,(struct Denoted*)object,translation_data);

	push_object_into_linkage(translation_data,object_declaration);

	Queue_Push(where_to_push,object_declaration);
}
struct Denotation_Prototype* parse_specifier_qualifier_list(struct Translation_Data *translation_data,struct Scope *scope)
{
	return parse_declaration_specifiers_inner(translation_data,scope,0);
}
struct Denotation_Prototype* parse_declaration_specifiers(struct Translation_Data *translation_data,struct Scope *scope)
{
	return parse_declaration_specifiers_inner(translation_data,scope,1);
}

/*declaration-specifiers:
 		( storage-class-specifier type-specifier type-qualifier function-specifier)* */
struct Denotation_Prototype* parse_declaration_specifiers_inner(struct Translation_Data *translation_data,struct Scope *scope,char parse_storage_class)
{
	enum LEXER_TYPE hold_kw;
	struct Denotation_Prototype *ret;
	ret=(struct Denotation_Prototype*)get_denotation_prototype(translation_data->program);

	while(1)
	{
		hold_kw=kw_get(translation_data);
		switch(hold_kw)
		{
			case KW_SIGNED:
				chomp(translation_data);
				if(ret->sign==TSIGN_NONE)
				{
					ret->sign=TSIGN_SIGNED;
				}
				else
				{
					push_generic_error(translation_data->program,"unexpected 'signed' in type");
					if(ret->sign==TSIGN_SIGNED)
						push_generic_note(translation_data->program,"when it is unsigned");
					else
						push_generic_note(translation_data->program,"when it is already signed");
				}
				break;
			case KW_UNSIGNED:
				chomp(translation_data);
				if(ret->sign==TSIGN_NONE)
				{
					ret->sign=TSIGN_UNSIGNED;
				}
				else
				{
					push_generic_error(translation_data->program,"unexpected 'unsigned' in type");
					if(ret->sign==TSIGN_SIGNED)
						push_generic_note(translation_data->program,"when it is signed");
					else
						push_generic_note(translation_data->program,"when it is already unsigned");
				}
				break;

			case KW_CONST:
				chomp(translation_data);
				ret->is_const=1;
				break;
			case KW_VOLATILE:
				chomp(translation_data);
				ret->is_volatile=1;
				break;
			case KW_INT:
				chomp(translation_data);
				if(ret->specifier!=TS_NONE)
				{
					push_generic_error(translation_data->program,"more than one type specifier given");
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->specifier=TS_INT;
				break;
			case KW_VOID:
				chomp(translation_data);
				if(ret->specifier!=TS_NONE)
				{
					push_generic_error(translation_data->program,"more than one type specifier given");
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->specifier=TS_VOID;
				break;
			case KW_CHAR:
				chomp(translation_data);
				if(ret->specifier!=TS_NONE)
				{
					push_generic_error(translation_data->program,"more than one type specifier given");
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->specifier=TS_CHAR;
				break;
			case KW_DOUBLE:
				chomp(translation_data);
				if(ret->specifier!=TS_NONE)
				{
					push_generic_error(translation_data->program,"more than one type specifier given");
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->specifier=TS_DOUBLE;
				break;
			case KW_FLOAT:
				chomp(translation_data);
				if(ret->specifier!=TS_NONE)
				{
					push_generic_error(translation_data->program,"more than one type specifier given");
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->specifier=TS_FLOAT;
				break;
			case KW_LONG:
				chomp(translation_data);
				if(ret->constraint!=TC_NONE)
				{
					if(ret->constraint==TC_LONG)
					{
						ret->constraint=TC_LONG_LONG;
						break;
					}else
					{
						if(ret->constraint==TC_LONG_LONG)
							push_generic_error(translation_data->program,"yeah ... it's big");
						else if(ret->constraint==TC_SHORT)
							push_generic_error(translation_data->program,"long and short constraints contradict");
						else 
							wonky_assert(SHOULD_NOT_REACH_HERE);
						return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
					}
				}
				ret->constraint=TC_LONG;
				break;
			case KW_SHORT:
				chomp(translation_data);
				if(ret->constraint!=TC_NONE)
				{
					switch(ret->constraint)
					{
						case TC_LONG:
						push_generic_error(translation_data->program,"long and short constraints contradict");
						break;
						case TC_SHORT:
						push_generic_error(translation_data->program,"it's not about the size, it's about how you use it");
						break;
						case TC_LONG_LONG:
						push_generic_error(translation_data->program,"long long and short constraints contradict");
						break;
						default:
						/*should not be able to enter here*/
						wonky_assert(SHOULD_NOT_REACH_HERE);
					}
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->constraint=TC_SHORT;
				break;
			case KW_EXTERN:
				if(!parse_storage_class)
					goto exit;
				chomp(translation_data);
				if(ret->storage_class!=SCS_NONE)
				{
					switch(ret->storage_class)
					{
						case SCS_EXTERN:
						push_generic_error(translation_data->program,"only one extern allowed >:|");
						break;

						case SCS_TYPEDEF:
						case SCS_STATIC:
						push_generic_error(translation_data->program,"only one storage class allowed >:|");
						break;
						default:
						wonky_assert(SHOULD_NOT_REACH_HERE);
					}

					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->storage_class=SCS_EXTERN;
				break;
			case KW_STATIC:
				if(!parse_storage_class)
					goto exit;
				chomp(translation_data);
				if(ret->storage_class!=SCS_NONE)
				{
					switch(ret->storage_class)
					{
						case SCS_STATIC:
						push_generic_error(translation_data->program,"only one static allowed >:|");
						break;

						case SCS_EXTERN:
						case SCS_TYPEDEF:
						push_generic_error(translation_data->program,"only one storage class allowed >:|");
						break;
						default:
						wonky_assert(SHOULD_NOT_REACH_HERE);
					}
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->storage_class=SCS_STATIC;
				break;
			case KW_TYPEDEF:
				if(!parse_storage_class)
					goto exit;
				chomp(translation_data);
				if(ret->storage_class!=SCS_NONE)
				{
					switch(ret->storage_class)
					{
						case SCS_STATIC:
						case SCS_EXTERN:
						case SCS_TYPEDEF:
						push_generic_error(translation_data->program,"only one storage class allowed >:|");
						break;
						default:
						wonky_assert(SHOULD_NOT_REACH_HERE);
					}
					return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
				}
				ret->storage_class=SCS_TYPEDEF;
				break;
			case KW_STRUCT:
				ret->specifier=TS_STRUCT;
				goto hack;
			case KW_UNION:
				ret->specifier=TS_UNION;
				hack:
				chomp(translation_data);
				if(check(translation_data,KW_ID))
				{
					struct identifier *id;
					struct token_identifier *hold_token;
					struct Denoted_Struct_Union *tag;

					hold_token=(struct token_identifier*)get_next_token(translation_data);

					wonky_assert(hold_token->type=KW_ID);

					id=hold_token->id;

					tag=(struct Denoted_Struct_Union*)check_tag(scope,id);

					if(tag==NULL)
					{
						struct Struct_Union *body;
						body=get_struct_union_base(scope,ret->specifier,id);
						Scope_Push(scope,get_denoted_struct_union(body),translation_data);

						parse_struct_union_specifier_finish(translation_data,scope,body);
						ret->struct_union=body;
					}else
					{
						ret->struct_union=tag->struct_union;
						if(ret->struct_union->specifier!=ret->specifier)
						{
							push_generic_error(translation_data->program,"more than one type specifier");
							return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
						}
						if(ret->struct_union->is_finished==0)
						{
							/*then this could be a definition*/
							parse_struct_union_specifier_finish(translation_data,scope,ret->struct_union);
						}
					}

				}else
				{
						ret->struct_union=get_struct_union_base(scope,ret->specifier,NULL);
						parse_struct_union_specifier_finish(translation_data,scope,ret->struct_union);
						if(ret->struct_union->is_finished==0)
						{
							push_generic_error(translation_data->program,"expected a struct tag or a struct definition");
							return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
						}
				}
				break;
			case KW_ENUM:
				chomp(translation_data);
				ret->specifier=TS_ENUM;
				if(check(translation_data,KW_ID))
				{
					struct identifier *id;
					struct token_identifier *hold_token;
					struct Denoted_Enum *enumerator;

					hold_token=(struct token_identifier*)get_next_token(translation_data);
					wonky_assert(hold_token->type=KW_ID);

					id=hold_token->id;
					enumerator=(struct Denoted_Enum*)check_tag(scope,id);
					if(enumerator==NULL)
					{
						struct Enum *body;
						body=get_enum_base(id);
						Scope_Push(scope,get_denoted_enum(body),translation_data);
						parse_enum_specifier_finish(translation_data,scope,body);
						ret->enumerator=body;
					}else
					{
						ret->enumerator=enumerator->enumeration;
						if(enumerator->denotation!=DT_Enum)
						{
							return (struct Denotation_Prototype*)get_denoted_error((struct Denoted*)ret);
						}
						if(ret->enumerator->is_finished==0)
						{
							/*this could be an enum definition*/
							parse_enum_specifier_finish(translation_data,scope,ret->enumerator);
						}
					}

				}else
				{
					/*tagless enumeration*/
					ret->enumerator=get_enum_base(NULL);
					parse_enum_specifier_finish(translation_data,scope,ret->enumerator);
				}
				break;
			case KW_ID:
				if(ret->specifier==TS_NONE)
				{
					struct Denoted *hold;
					struct token_identifier *hold_token;
					struct identifier *id;

					hold_token=(struct token_identifier*)get_next_token(translation_data);

					wonky_assert(hold_token->type=KW_ID);

					id=hold_token->id;

					hold=check_ordinary(scope,id);
					if(hold!=NULL && hold->denotation==DT_Typedef)
					{
						ret->type=((struct Denoted_Type*)hold)->type;
						chomp(translation_data);
						return ret;
					}
					/*falltrough - this has not been typedefed*/
				}
				/*falltrough (it is possible to overwrite typedef id from upper scope)*/
			default:
			exit:
				if(ret->specifier==TS_ENUM)
				{
					ret->type=(struct Type*)get_enum_type(ret);
				}else if(ret->specifier==TS_STRUCT || ret->specifier==TS_UNION)
				{
					ret->type=(struct Type*)get_struct_union_type(ret);
				}else if(ret->type==NULL)
				{
					ret->type=(struct Type*)get_basic_type(ret);
				}
				return ret;
		}
	}
}





/*
   	declarator:
		( pointer ( type-qualifier )* )* direct-declarator
 */
struct Denoted* parse_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denotation_Prototype *prototype)
{
	struct Denoted_Base *temp;
	struct Denoted *ret;
	temp=get_denoted_base(prototype);
	parse_declarator_inner(translation_data,scope,temp);
	ret=extract_denoted(temp,prototype,0);
	delete_denoted_base(temp);
	return ret;

}

void parse_declarator_inner(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Base *base)
{
	enum LEXER_TYPE hold;
	char is_const;
	char is_volatile;
	while(get_and_check(translation_data,KW_STAR))
	{
		is_const=is_volatile=0;
		while(1)
		{
			hold=kw_get(translation_data);
			if(hold==KW_CONST)
			{
				chomp(translation_data);
				is_const=1;
			}else if(hold==KW_VOLATILE)
			{
				chomp(translation_data);
				is_volatile=1;
			}else
			{
				break;
			}
		}
		base->type=(struct Type*)get_pointer_type(base->type,is_const,is_volatile);
	}
	parse_direct_declarator(translation_data,scope,base);

}
/*
	direct-declarator:
		id direct-declarator-finish
		( declarator ) direct-declarator-finish
*/
void parse_direct_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Base *base)
{
	if(check(translation_data,KW_ID))
	{
		struct token_identifier *hold_token;
		struct identifier *id;

		hold_token=(struct token_identifier*)get_next_token(translation_data);
		wonky_assert(hold_token->type=KW_ID);
		id=hold_token->id;

		base->id=id;
		parse_direct_declarator_finish(translation_data,scope,base);
		
	}else if(get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		struct Type *hold_first_part;
		struct Type *hold_middle_part;
		hold_first_part=base->type;
		base->type=NULL;
		parse_declarator_inner(translation_data,scope,base);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			hold_middle_part=base->type;
			base->type=hold_first_part;
			parse_declarator_inner(translation_data,scope,base);
			if(!rebase_type(hold_middle_part,base->type))
			{
				base->type=hold_middle_part;
			}else
			{
				wonky_assert(SHOULD_NOT_REACH_HERE);
			}
		}else
		{
			base->type=get_type_error(hold_first_part);
			push_generic_error(translation_data->program,"Expected a ')' at %L");
		}
	}else
	{
		/*this might be an abstract declarator*/
		parse_direct_declarator_finish(translation_data,scope,base);
	}
}

/*
	direct-declarator-finish:
		( [ constant-expression ] | (parameter-list) | ( [id-list] ) )* 
*/
void parse_direct_declarator_finish(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Base *base)
{
	struct AST *hold_expression;
	while(1)
	{
		if(get_and_check(translation_data,KW_OPEN_SQUARE))
		{
			if(get_and_check(translation_data,KW_CLOSE_SQUARE))
			{
				hold_expression=NULL;
			}else
			{
				hold_expression=parse_expression(translation_data,scope);
				if(!get_and_check(translation_data,KW_CLOSE_SQUARE))
				{
					/*TODO error*/
					push_generic_error(translation_data->program,"']' expected");
					base->type=(struct Type*)get_type_error(base->type);
					delete_ast(hold_expression);
					return;
				}
			}

			parse_direct_declarator_finish(translation_data,scope,base);
			base->type=get_array_type(base->type,hold_expression,translation_data);

		}else if(get_and_check(translation_data,KW_OPEN_NORMAL))
		{
			struct Queue *parameters;
			struct Normal_Scope *function_prototype_scope;
			_Bool is_variadic=0;

			function_prototype_scope=(struct Normal_Scope*)get_normal_scope(scope,FUNCTION_PROTOTYPE_SCOPE);

			parameters=wonky_malloc(sizeof(struct Queue));
			Queue_Init(parameters);

			is_variadic=parse_paramenter_list(translation_data,function_prototype_scope,parameters);
			base->type=(struct Type*)get_function_type(base->type,parameters,function_prototype_scope,is_variadic,translation_data);
			
		}else
		{
			break;
		}
		
	}

}


/*
	struct-union-specifier-finish:
		{ ( struct-declaration )* }
 */
void parse_struct_union_specifier_finish(struct Translation_Data *translation_data,struct Scope *scope,struct Struct_Union *base)
{
	if(get_and_check(translation_data,KW_OPEN_CURLY))
	{
		base->is_finished=1;
		while(parse_struct_declaration(translation_data,base))
			if(get_and_check(translation_data,KW_CLOSE_CURLY))
				return ;
		/*TODO error*/
		push_generic_error(translation_data->program,"expected closing curly bracket from struct declaration");
		return;
	}
}
/*
   struct-declaration:
		specifier-qualifier-list  ( struct-declarator )*  ;
   */
char parse_struct_declaration(struct Translation_Data *translation_data,struct Struct_Union *base)
{
	struct Denotation_Prototype *prototype;
	struct Denoted *hold_denoted;
	struct Denoted_Object *hold_denoted_object;

	prototype=parse_specifier_qualifier_list(translation_data,(struct Scope*)base->inner_namespace);
	while(!get_and_check(translation_data,KW_SEMICOLON))
	{
		hold_denoted=parse_struct_declarator(translation_data,(struct Scope*)base->inner_namespace,prototype);
		if(hold_denoted!=NULL && hold_denoted->denotation!=DT_Error)
		{
			if(hold_denoted->denotation==DT_Object)
			{
				hold_denoted_object=(struct Denoted_Object*)hold_denoted;
				
				Scope_Push((struct Scope*)base->inner_namespace,hold_denoted,translation_data);
				Queue_Push(base->members,hold_denoted);
				if(type_is_constant_or_has_constant_member(hold_denoted_object->object->type))
					base->has_constant_member=1;
			}else
			{
				push_generic_error(translation_data->program,"non object declaration in struct definition");
			}

		}else
		{
			wonky_free(prototype);
			push_generic_error(translation_data->program,"there is a problem with the declarator");
			return 0;
		}

		if(!get_and_check(translation_data,KW_COMMA) && !check(translation_data,KW_SEMICOLON))
		{
			wonky_free(prototype);
			push_generic_error(translation_data->program,"semi column expected in struct declaration");
			return 0;
		}
	}
	wonky_free(prototype);
	return 1;

}
/*
	struct-declarator:
		declarator
		[ declarator ] : constant-expression
 */
struct Denoted* parse_struct_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denotation_Prototype *prototype)
{
	struct Denoted_Object *hold_denoted_object;
	struct AST_Expression *hold_number_of_bits_expression;

	if(get_and_check(translation_data,KW_COLUMN))
	{
		/*unnamed bitfields are possible*/
		hold_denoted_object=(struct Denoted_Object*)get_denoted_object(NULL,SCS_NONE,prototype->type,NULL);

	}else
	{
		/*we cast it but it is still unsure if it has object type so we imediately check*/
		hold_denoted_object=(struct Denoted_Object*)parse_declarator(translation_data,scope,prototype);
		if(hold_denoted_object->denotation!=DT_Object)
		{
			/*TODO error*/
			push_generic_error(translation_data->program,"expected object type for bitfield");
			return get_denoted_error((struct Denoted*)hold_denoted_object);
		}
		if(get_and_check(translation_data,KW_COLUMN))
		{
			hold_number_of_bits_expression=(struct AST_Expression*)parse_expression(translation_data,scope);

			hold_denoted_object->object=convert_object_to_bitfield(hold_denoted_object->object,hold_number_of_bits_expression,translation_data);
		}
	}
	
	return (struct Denoted*)hold_denoted_object;
}
/*
	enum-specifier-finish
	{ ( enumeration-constant [ = constant-expression ] , )* }
*/
void parse_enum_specifier_finish(struct Translation_Data *translation_data,struct Scope *scope,struct Enum *enumeration)
{
	struct identifier *id;
	struct Denoted_Enum_Const *hold;
	int where_in_enumeration=0;
	if(get_and_check(translation_data,KW_OPEN_CURLY))
	{
		enumeration->is_finished=1;
		do
		{
			if(check(translation_data,KW_ID))
			{
				id=((struct token_identifier*)get_next_token(translation_data))->id;
				if(get_and_check(translation_data,KW_EQ))
				{
					hold=(struct Denoted_Enum_Const*)get_denoted_enum_const_expr(id,enumeration,parse_expression(translation_data,scope),translation_data);
					Queue_Push(enumeration->consts,hold);
					where_in_enumeration=hold->value+1;
				}else
				{
					Queue_Push(enumeration->consts,get_denoted_enum_const_num(id,enumeration,where_in_enumeration));
					++where_in_enumeration;
				}
				if(!get_and_check(translation_data,KW_COMMA) && get_and_check(translation_data,KW_CLOSE_CURLY))
				{
					return;
				}else
				{
					/*TODO error*/
					push_generic_error(translation_data->program,"enum definition error");
					Queue_Push(enumeration->consts,get_denoted_error(NULL));
					return ;
				}
			}else
			{
				/*TODO error*/
				push_generic_error(translation_data->program,"enum definition error, expected an id");
				Queue_Push(enumeration->consts,get_denoted_error(NULL));
				return ;
			}
		}while(!get_and_check(translation_data,KW_CLOSE_CURLY));

	}
}

/*
	parameter-list:
		(declaratoion-specifiers (declarator | abstract-declarator),)* [ ... ]

	returns 1 if it's a variadic function
		0 otherwise
*/
_Bool parse_paramenter_list(struct Translation_Data *translation_data,struct Normal_Scope *function_prototype_scope,struct Queue *parameters)
{
	if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		return 0;

	struct Denotation_Prototype *prototype;
	struct Denoted_Base *base;
	struct Denoted *hold;
	_Bool is_variadic=0;
	do
	{
		
		if(get_and_check(translation_data,KW_ELIPSIS))
		{
			is_variadic=1;
			break;
		}

		prototype=parse_declaration_specifiers(translation_data,(struct Scope*)function_prototype_scope);
		base=get_denoted_base(prototype);


		parse_declarator_inner(translation_data,(struct Scope*)function_prototype_scope,base);
		if(base->denotation!=DT_Object)
		{
			/*TODO error*/
			push_generic_error(translation_data->program,"expected object declaration in function prototype");
		//	delete_denoted(hold);
			delete_denoted_prototype(prototype);
			delete_denoted_base(base);	
			return 0;
		}

		hold=extract_denoted(base,prototype,1);

		if(((struct Denoted_Object*)hold)->id!=NULL)
			Scope_Push((struct Scope*)function_prototype_scope,hold,translation_data);
		Queue_Push(parameters,((struct Denoted_Object*)hold));

		delete_denoted_prototype(prototype);
		delete_denoted_base(base);	

	}while(get_and_check(translation_data,KW_COMMA));


	if(!get_and_check(translation_data,KW_CLOSE_NORMAL))
	{
		/*TODO error*/
		push_translation_error("expected a ')' finishing the parameter list",translation_data);
		Queue_Push(parameters,get_denoted_error(NULL));
	}

	return is_variadic;
}
/*
	type-name:
		specifier-qualifier-list [abstract-declarator]
*/
struct Type* parse_type_name(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct Denotation_Prototype *prototype;
	struct Type *ret;
	prototype=parse_specifier_qualifier_list(translation_data,scope);
	ret=parse_abstract_declarator(translation_data,scope,prototype);
	delete_denoted_prototype(prototype);
	return ret;
}
/*
   	abstract-declarator:
		( pointer )* abstract-direct-declarator
*/
struct Type* parse_abstract_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denotation_Prototype *prototype)
{
	struct Denoted_Base *base;
	struct Type *ret;


	base=get_denoted_base(prototype);
	parse_declarator_inner(translation_data,scope,base);

	if(base->denotation==DT_Error || base->id!=NULL)
	{
		/*TODO error*/
		push_generic_error(translation_data->program,"unexpedted id in abstract declarator");
		delete_denoted_base(base);
		ret=base->type;
		return ret;
	}
	ret=base->type;
	delete_denoted_base(base);
	return ret;

}

/*
	initializer:
		assignment-expression
		{ initializer-list [,] }
*/

struct Initialiser* parse_initialiser(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	if(get_and_check(translation_data,KW_OPEN_CURLY))
		return parse_initialiser_list(translation_data,scope,type_of_initialised);
	else
		return parse_simple_initialiser(translation_data,scope,type_of_initialised);
}

/*
 	initilizer-list:
		( initialiser-list-component ',' )*

 */
struct Initialiser* parse_initialiser_list(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	if(type_is_an_array(type_of_initialised))
		return parse_initialiser_list_for_array(translation_data,scope,(struct Type_Array*)type_of_initialised);
	else if(type_is_struct_union(type_of_initialised))
		return parse_initialiser_list_for_struct_union(translation_data,scope,(struct Type_Struct_Union*)type_of_initialised);
	else
	{
		push_generic_error(translation_data->program,"expected aggregate type in compound initialisation, got %T instead",type_of_initialised);
		return get_initialiser_error(NULL);
	}
}

/*
 	initilizer-list:
		( initialiser-list-component ',' )*

 */
struct Initialiser* parse_initialiser_list_for_struct_union(struct Translation_Data *translation_data,struct Scope *scope,struct Type_Struct_Union *type_of_initialised)
{
	struct Queue_Node *current_object;
	struct Initialiser *current_initialiser;
	struct Queue *components;

	current_object=type_of_initialised->struct_union->members->first;

	components=wonky_malloc(sizeof(struct Queue));
	Queue_Init(components);

	do{
		current_initialiser=parse_initialiser_list_component(translation_data,scope,(struct Type*)type_of_initialised);
		if(current_initialiser->kind==INITIALISER_ERROR)
		{
			return current_initialiser;
		}else if(current_initialiser->kind!=INITIALISER_DENOTED)
		{
			Queue_Push(
			components,
			get_denoted_initialiser((struct Denoted_Object*)current_object->data,current_initialiser,translation_data)
			);
			current_object=current_object->prev;
		}else
		{
			for(
				current_object=type_of_initialised->struct_union->members->first;	
				current_object!=NULL && current_object->data!=((struct Initialiser_Denoted*)current_initialiser)->to_be_initialised;
				current_object=current_object->prev
			   );
			current_object=current_object->prev;
			Queue_Push(components,current_initialiser);
			

		}
	}while(get_and_check(translation_data,KW_COMMA));

	if(get_and_check(translation_data,KW_CLOSE_CURLY))
		return get_compound_initialiser((struct Type*)type_of_initialised,components,translation_data);
	else
		return get_initialiser_error(get_compound_initialiser((struct Type*)type_of_initialised,components,translation_data));
}

/*
 	initilizer-list:
		( initialiser-list-component ',' )*

 */
struct Initialiser* parse_initialiser_list_for_array(struct Translation_Data *translation_data,struct Scope *scope,struct Type_Array *type_of_initialised)
{
	struct Queue *components;
	size_t current_object;
	struct Initialiser *current_initialiser;

	components=wonky_malloc(sizeof(struct Queue));
	Queue_Init(components);

	do{
		current_initialiser=parse_initialiser_list_component(translation_data,scope,(struct Type*)type_of_initialised);
		if(current_initialiser->kind==INITIALISER_ERROR)
		{
			return current_initialiser;
		}else if(current_initialiser->kind!=INITIALISER_INDEXED)
		{
			Queue_Push(
				components,
				get_indexed_initialiser(type_of_initialised->is_array_of,current_object,current_initialiser,translation_data)
			);
			++current_object;
		}else
		{
			Queue_Push(components,current_initialiser);
			current_object=((struct Initialiser_Indexed*)current_initialiser)->index+1;
		}
	}while(get_and_check(translation_data,KW_COMMA));

	if(get_and_check(translation_data,KW_CLOSE_CURLY))
		return get_compound_initialiser((struct Type*)type_of_initialised,components,translation_data);
	else
		return get_initialiser_error(get_compound_initialiser((struct Type*)type_of_initialised,components,translation_data));
}

/*
	assignment-expression 
 */
struct Initialiser* parse_simple_initialiser(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	struct AST_Expression *assignment_expression;

	assignment_expression=parse_assignment_expression(translation_data,scope);
	
	return get_initialiser_expression(assignment_expression,type_of_initialised,translation_data);
}

/*
 	initialiser-list-component:
		[ designation ] initialiser 
*/
struct Initialiser* parse_initialiser_list_component(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	if(check(translation_data,KW_DOT) || check(translation_data,KW_OPEN_SQUARE))
		return parse_designation(translation_data,scope,type_of_initialised);
	else
		return parse_initialiser(translation_data,scope,type_of_initialised);
}

/*
	designation:
		designator-list '='
	designator-list:
		( designator )+
	designator:
		'[' constant-expression ']'
		'.' identifier
*/
/*TODO: make this iterative XD*/
struct Initialiser* parse_designation(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	if(get_and_check(translation_data,KW_OPEN_SQUARE))
		parse_indexed_initialiser(translation_data,scope,type_of_initialised);
	else if(get_and_check(translation_data,KW_DOT))
		parse_member_initialiser(translation_data,scope,type_of_initialised);
	else if(get_and_check(translation_data,KW_EQ))
		return parse_initialiser(translation_data,scope,type_of_initialised);
	else
	{
		push_generic_error(translation_data->program,"expected '=' in initialiser designation");
		return get_initialiser_error(NULL);
	}

}
struct Initialiser* parse_indexed_initialiser(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	struct AST_Expression *index_expression;
	struct Type_Array *real_type;

	if(!type_is_an_array(type_of_initialised))
	{
		push_generic_error(translation_data->program,"expected array type in indexed initialiser, instead got a %T",type_of_initialised);
		return get_initialiser_error(NULL);
	}

	real_type=(struct Type_Array*)type_of_initialised;
	index_expression=(struct AST_Expression*)parse_expression(translation_data,scope);

	if(get_and_check(translation_data,KW_CLOSE_CURLY))
	{
		size_t eval;
		eval=evaluate_const_expression_integer((struct AST*)index_expression,translation_data);
		return get_indexed_initialiser(real_type->is_array_of,eval,parse_designation(translation_data,scope,real_type->is_array_of),translation_data);
	}else
	{
		size_t eval;
		eval=evaluate_const_expression_integer((struct AST*)index_expression,translation_data);
		return get_initialiser_error(
				get_indexed_initialiser(real_type->is_array_of,eval,parse_designation(translation_data,scope,real_type->is_array_of),translation_data)
				);
	}
}
struct Initialiser* parse_member_initialiser(struct Translation_Data *translation_data,struct Scope *scope,struct Type *type_of_initialised)
{
	struct Denoted_Object *member;
	struct Type_Struct_Union *real_type;
	struct identifier *id;

	if(!type_is_struct_union(type_of_initialised))
	{
		push_generic_error(translation_data->program,"expected struct/union type in initialiser, got %T instead",type_of_initialised);
		return get_initialiser_error(NULL);
	}
	if(!check(translation_data,KW_ID))
	{
		push_generic_error(translation_data->program,"expected id in the initialisation of type %T",type_of_initialised);
		return get_initialiser_error(NULL);
	}

	id=((struct token_identifier*)get_next_token(translation_data))->id;
	real_type=(struct Type_Struct_Union*)type_of_initialised;
	member=check_struct_union_member(real_type->struct_union->inner_namespace,id);

	if(member==NULL)
	{
		push_generic_error(translation_data->program,"%t is not a member of %T",id,type_of_initialised);
		push_translation_note("in initialiser",translation_data);
		return get_initialiser_error(NULL);
	}

	return get_denoted_initialiser(member,parse_initialiser(translation_data,scope,member->object->type),translation_data);
}

const const const const const const const const const const const const const const const const const const const const const const const char const const const constant;
#endif