MEGATRON



LOG | FILES | OVERVIEW


#ifndef PARSER_C
#define PARSER_C PARSER_C
#include <parser.h>

struct AST* parse_source(struct Translation_Data *translation_data)
{
	return (struct AST*)parse_translation_unit(translation_data);
}
/*
 * translation-unit: (machine)*
 */
struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *translation_data)
{
	struct Queue *machines;
	struct Map *hold_command_map;
	struct Map *hold_machines_map;
	struct AST_Machine *hold_machine;
	struct AST_Machine *hold_possible_duplicate;

	machines=calloc(1,sizeof(struct Queue));

	hold_command_map=malloc(sizeof(struct Map));
	Map_Init(hold_command_map);

	hold_machines_map=malloc(sizeof(struct Map));
	Map_Init(hold_machines_map);

	translation_data->hold_command_map=hold_command_map;

	while(!get_and_check(translation_data,KW_EOF))
	{
		hold_machine=parse_machine(translation_data);
		if(hold_machine)
		{
			if(hold_possible_duplicate=Map_Check(hold_machines_map,hold_machine->id->data,hold_machine->id->size))
			{
				push_error_with_token("duplicate machine name",hold_machine->id,translation_data);
				push_error_with_token("conflicts with",hold_possible_duplicate->id,translation_data);
				delete_ast_machine(hold_machine);
				return NULL;
			}else
			{
				Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
				Queue_Push(machines,hold_machine);
			}
		}
		else
		{
			return NULL;
		}
	}
	return get_ast_translation_unit(machines,hold_command_map,hold_machines_map);
}
/*
 * machine: 'machine' id '[' machine-inner ']' ';'
 *
 */
struct AST_Machine* parse_machine(struct Translation_Data *translation_data)
{
	struct AST_Machine *ret;
	struct token *hold_id;
	if(get_and_check(translation_data,KW_MACHINE))
	{
		if(get_kw(translation_data)==KW_ID) 
		{
			hold_id=Queue_Pop(translation_data->tokens);
			if(get_and_check(translation_data,KW_OPEN_SQUARE))
			{
				ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data);
				if(has_new_errors(translation_data))
				{
					touch_errors(translation_data);

					return NULL;
				}
				if(get_and_check(translation_data,KW_CLOSE_SQUARE))
				{
					if(get_and_check(translation_data,KW_SEMI_COLUMN))
						return ret;
					else
					{
						push_parsing_error("';' expected after machine definition",translation_data);
						return NULL;
					}
				}else
				{
					push_parsing_error("closing ']' expected",translation_data);
					return NULL;
				}
			}else
			{
				push_parsing_error("opening '[' expected",translation_data);
				return NULL;
			}
		}else
		{
				push_parsing_error("expected a name for the machine",translation_data);
				return NULL;
		}
	}else
	{
		push_parsing_error("'machine' expected",translation_data);
		return NULL;
	}
}
/*
 * machine-inner : 'states' '[' states-inner ']' ';'
 * 		   'events' '[' events-inner ']' ';'
 * 		   'transitions' '[' transitions-inner ']' ';'
 * 		   'starting' start-on-inner ';'
 */
struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data)
{
	struct AST_States *states=NULL;
	struct AST_Events *events=NULL;
	struct AST_Transitions *transitions=NULL;
	struct AST_State *starting_state=NULL;
	unsigned char i;
	for(i=0;i<4;++i)
		switch(get_kw(translation_data))
		{
			case KW_STATES:
				if(states)
				{
					push_parsing_error("defining two sets of states",translation_data);
					goto error_cleanup;
				}else
				{
					chomp(translation_data);
					if(get_and_check(translation_data,KW_OPEN_SQUARE))
					{
						states=parse_states_inner(translation_data);
						if(!get_and_check(translation_data,KW_CLOSE_SQUARE) 
								|| !get_and_check(translation_data,KW_SEMI_COLUMN))
						{
							push_parsing_error("expected ']' and ';' at "
									"end of states definition",translation_data);
							goto error_cleanup;
						}

					}else
					{
						push_parsing_error("expected '[' ",translation_data);
						goto error_cleanup;
					}
				}
				break;
			case KW_TRANSITIONS:
				if(states==NULL && events==NULL)
				{
					push_parsing_error("defining transitions before states and events",translation_data);
					goto error_cleanup;
				}else if(transitions)
				{
					push_parsing_error("defining two sets of transitions",translation_data);
					goto error_cleanup;
				}else
				{
					chomp(translation_data);
					if(get_and_check(translation_data,KW_OPEN_SQUARE))
					{
						transitions=parse_transitions_inner(translation_data,states,events);
						if(!get_and_check(translation_data,KW_CLOSE_SQUARE) 
								|| !get_and_check(translation_data,KW_SEMI_COLUMN))
						{
							push_parsing_error("expected ']' and ';' at "
									"end of transitions definition",translation_data);
							goto error_cleanup;
						}
					}else
					{
						push_parsing_error("expected '[' ",translation_data);
						goto error_cleanup;
					}
				}
				break;
			case KW_EVENTS:
				if(events)
				{
					push_parsing_error("defining two sets of transitions",translation_data);
					goto error_cleanup;
				}else
				{
					chomp(translation_data);
					if(get_and_check(translation_data,KW_OPEN_SQUARE))
					{
						events=parse_events_inner(translation_data);
						if(!get_and_check(translation_data,KW_CLOSE_SQUARE) 
								|| !get_and_check(translation_data,KW_SEMI_COLUMN))
						{
							push_parsing_error("expected ']' and ';' at "
									"end of events definition",translation_data);
							goto error_cleanup;
						}
					}else
					{
						push_parsing_error("expected '[' ",translation_data);
						goto error_cleanup;
					}
				}
				break;
			case KW_STARTING:
				chomp(translation_data);
				if(!starting_state)
				{
					if(states)
					{
						starting_state=parse_start_on(translation_data,states);
						if(!get_and_check(translation_data,KW_SEMI_COLUMN))
						{
							push_parsing_error("expected ';' at end "
									"of starting state declaration",translation_data);
							goto error_cleanup;
						}
					}else
					{
						push_parsing_error("states need to be defined"
							" before defining a starting one",translation_data);
						goto error_cleanup;
					}
				}else
				{
					push_parsing_error("starting state is defined",translation_data);
					goto error_cleanup;
				}
				break;
			default:
				push_parsing_error("expected states transitions or events",translation_data);
				goto error_cleanup;

		}

	return get_ast_machine(machine_id,states,events,transitions,starting_state);

error_cleanup:
	push_parsing_error("in machine",translation_data);
	return NULL;
}
/*
 * states-inner: state (, state)*
 * 
 */
struct AST_States* parse_states_inner(struct Translation_Data *translation_data)
{
	struct Queue *ids;
	struct AST_State *hold_state;
	
	ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA);
	if(ids->size==0)
	{
		push_parsing_error("there needs to be atleast one state",translation_data);
		free(ids);
		return NULL;
	}else
	{

		return get_ast_states(ids,translation_data);
	}
}
/*
 * state : id [ '[' ( 'on' 'entering' statement | 'on 'exiting'  statement )* ']' ]
 *
 */
struct AST_State* parse_state(struct Translation_Data *translation_data)
{
	struct token *hold_id;
	struct AST *hold_entry=NULL;
	struct AST *hold_exit=NULL;
	int i;

	if(get_kw(translation_data)==KW_ID)
	{
		hold_id=Queue_Pop(translation_data->tokens);

		if(get_and_check(translation_data,KW_OPEN_SQUARE))
		{
			for(i=0;i<2;++i)
				if(get_and_check(translation_data,KW_ON))
				{
					if(get_and_check(translation_data,KW_ENTERING))
						hold_entry=parse_statement(translation_data);
					else if(get_and_check(translation_data,KW_EXITING))
						hold_exit=parse_statement(translation_data);
					else 
						break;
				}
			if(!get_and_check(translation_data,KW_CLOSE_SQUARE))
			{
				if(hold_entry)
				       	delete_ast(hold_entry);
				if(hold_exit)
					delete_ast(hold_exit);
				delete_token(hold_id);
				push_parsing_error("missing closing ']' in state definition",translation_data);
				return NULL;
			}

		}
		return get_ast_state(hold_id,hold_entry,hold_exit);
	}else
	{
		return NULL;
	}
}
/*
 * events-inner: id (, id)*
 * 
 */
struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)
{
	struct Queue *ids;
	ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA);
	if(ids->size==0)
	{
		push_parsing_error("there needs to be atleast one event",translation_data);
		return NULL;
	}else
	{
		return get_ast_events(ids);
	}
}
struct AST_Event* parse_event(struct Translation_Data *translation_data)
{
	if(get_kw(translation_data)==KW_ID)
		return get_ast_event(Queue_Pop(translation_data->tokens));
	else
		return NULL;
}
/*
 * transitions-inner: ( transition ;)*
 */
struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
{
	struct Queue *transitions;
	struct AST_Transition *hold_transition;

	transitions=malloc(sizeof(struct Queue));
	Queue_Init(transitions);
	
	while((hold_transition=parse_transition(translation_data,states,events))!=NULL)
	{
		Queue_Push(transitions,hold_transition);
	}

	if(transitions->size==0)
	{
		push_parsing_error("there are no transitions",translation_data);
		return NULL;
	}else if(has_new_errors(translation_data))
	{
		push_parsing_error("in transition",translation_data);
		return NULL;
	}else
	{
		return get_ast_transitions(transitions);
	}
}
/*
 * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ granted-part ] [ statement-part ]
 *
 */
struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
{
	struct AST_Transition *ret;
	struct AST_State *hold_from;
	struct AST_State *hold_to;
	struct AST_Event *hold_event;
	struct AST *hold_statement=NULL;
	struct AST *hold_granted=NULL;
	struct token *hold_token;

	if(get_and_check(translation_data,KW_FROM))
	{
		if(get_kw(translation_data)==KW_ID)
		{
			hold_token=Queue_Pop(translation_data->tokens);
			hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
			if(hold_from!=NULL)
			{
				if(get_and_check(translation_data,KW_TO))
				{
					if(get_kw(translation_data)==KW_ID)
					{
						hold_token=Queue_Pop(translation_data->tokens);
						hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
						delete_token(hold_token);
						if(hold_to!=NULL)
						{
							if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
							{
								if(get_kw(translation_data)==KW_ID)
								{
									hold_token=Queue_Pop(translation_data->tokens);
									hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
									delete_token(hold_token);
									if(hold_event!=NULL)
									{
										hold_granted=parse_transition_granted(translation_data,states,events);
										
					if(!get_and_check(translation_data,KW_SEMI_COLUMN) && (hold_statement=parse_statement(translation_data))==NULL)
						{ push_parsing_error("in statement of transition",translation_data); return NULL; }

										/*GOAL!!!!!*/
										return get_ast_transition(hold_from,hold_to,hold_event,hold_granted,hold_statement);
									}else { push_parsing_error("event not defined",translation_data); return NULL; }
								}else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
							}else { push_parsing_error("expected 'on event'",translation_data); return NULL; }	
						}else { push_parsing_error("using undefined to state in transition",translation_data); }
					}else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
				}else { push_parsing_error("expected 'to'",translation_data); return NULL; }	
			}else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
		}else { push_parsing_error("expected state id in from field",translation_data); return NULL; }
	}else { return NULL; }
}

/*
 * granted-part : 'granted' expression
 */
struct AST* parse_transition_granted(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
{
	if(get_and_check(translation_data,KW_GRANTED))
	{
		return parse_expression(translation_data);
	}else
	{
		return NULL;
	}
}

/*
 * statement : 'execute' pipeline ; | 'if' expression statement [ else statement ]
 */
struct AST* parse_statement(struct Translation_Data *translation_data)
{
	struct AST *hold_expression;
	struct AST *hold_body;
	struct AST *hold_else=NULL;

	if(get_and_check(translation_data,KW_EXECUTE))
	{
		hold_body=(struct AST*)parse_pipeline(translation_data);
		if(get_and_check(translation_data,KW_SEMI_COLUMN))
		{
			return hold_body;
		}else
		{
			push_parsing_error("expected ';' at the end of pipeline",translation_data);
			return NULL;
		}
	}else if(get_and_check(translation_data,KW_IF))
	{
		hold_expression=parse_expression(translation_data);
		hold_body=parse_statement(translation_data);
		if(hold_body)
		{
			if(get_and_check(translation_data,KW_ELSE))
			{
				hold_else=parse_statement(translation_data);
				if(hold_else==NULL)
				{
					push_parsing_error("expected a statement after else",translation_data);	
					return NULL;
				}
			}
			return (struct AST*)get_ast_if_statement(hold_expression,hold_body,hold_else);
		}else
		{
			push_parsing_error("expected body statement in if",translation_data);
			return NULL;
		}
	}else
	{
		push_parsing_error("expected 'execute' in statement",translation_data);
		return NULL;
	}
}
/*
 * pipeline: [ command ( | command )* ]
 *
 */
struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data)
{
	struct Queue *pipeline;
	pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE);
	if(pipeline->size==0)
	{
		free(pipeline);
		push_parsing_error("pipeline is empty",translation_data);
		return NULL;
	}else
	{
		return get_ast_pipeline(pipeline);
	}
}
/*
 * command: id [ string ]
 *
 */
struct AST_Command* parse_command(struct  Translation_Data *translation_data)
{
	struct token *id;
	struct token *string=NULL;
	struct AST_Command *ret;

	if(get_kw(translation_data)==KW_ID)
	{
		id=Queue_Pop(translation_data->tokens);
		if(get_kw(translation_data)==KW_STRING)
			string=Queue_Pop(translation_data->tokens);
		ret=get_ast_command(id,string);
		if(!Map_Check(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size))
			Map_Push(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size,ret);

		return ret;
	}else
	{
		push_parsing_error("expected command id",translation_data);
		return NULL;
	}
}
/*
 * starting-on-inner: 'on' id ;
 */
struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states)
{
	struct token *hold_id;
	struct AST_State *hold_state;

	if(get_and_check(translation_data,KW_ON))
	{
		if(get_kw(translation_data)==KW_ID)
		{
			hold_id=Queue_Pop(translation_data->tokens);
			hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size);
			free(hold_id);
			if(hold_state)
			{

					return hold_state;

			}else { push_parsing_error("starting state is not defined",translation_data); return NULL; }
		}else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; }
	}else { push_parsing_error("expected 'on'",translation_data); return NULL; }
}
struct AST_State* get_ast_state(struct token *id,struct AST *entry,struct AST *exit)
{
	struct AST_State *ret;
	assert(entry==NULL || entry->type==AST_TYPE_COMMAND || entry->type==AST_TYPE_PIPELINE || entry->type==AST_TYPE_IF);
	assert(exit==NULL || exit->type==AST_TYPE_COMMAND || exit->type==AST_TYPE_PIPELINE || exit->type==AST_TYPE_IF);

	ret=malloc(sizeof(struct AST_State));
	ret->type=AST_TYPE_STATE;
	ret->name=id;
	ret->on_entry_statement=entry;
	ret->on_exit_statement=exit;
	
	/*number is assigned in get_ast_states*/
	/*parent machine is determined in anotation stage*/

	return ret;
}
struct AST_Event* get_ast_event(struct token *id)
{
	struct AST_Event *ret;

	ret=malloc(sizeof(struct AST_Event));

	ret->name=id;

	return ret;
}
struct AST_States* get_ast_states(struct Queue *states,struct Translation_Data *translation_data)
{
	struct AST_States *ret;
	struct AST_State *hold_state;

	/*perhaps no states error should be handled here*/
	assert(states && states->size>0);

	ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size]));
	ret->type=AST_TYPE_STATES;
	ret->number_of_states=states->size;
	ret->states_map=malloc(sizeof(struct Map));

	Map_Init(ret->states_map);

	while(states->size>0)
	{
		hold_state=Queue_Pop(states);

		if(Map_Check(ret->states_map,hold_state->name->data,hold_state->name->size))
		{
			size_t i;

			push_error_with_token("duplicate state in states definition",hold_state->name,translation_data);

			for(i=states->size+1;i<ret->number_of_states;++i)
				delete_ast_state(ret->states[i]);
			delete_ast_state(hold_state);
			while(states->size>0)
				delete_ast_state(Queue_Pop(states));

			return NULL;
		}else
		{
			Map_Push(ret->states_map,hold_state->name->data,hold_state->name->size,hold_state);
		}

		ret->states[states->size]=hold_state;
		hold_state->number=states->size;
	}

	assert(states->size==0);
	free(states);

	return ret;
}
struct AST_Events* get_ast_events(struct Queue *events)
{
	struct AST_Events *ret;
	struct AST_Event *hold_event;

	/*perhaps no events error should be handled here*/
	assert(events && events->size>0);

	ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size]));
	ret->type=AST_TYPE_EVENTS;
	ret->number_of_events=events->size;
	ret->events_map=malloc(sizeof(struct Map));

	Map_Init(ret->events_map);

	while(events->size>0)
	{
		hold_event=Queue_Pop(events);
		/*TODO check for redeclaration*/
		Map_Push(ret->events_map,hold_event->name->data,hold_event->name->size,hold_event);
		ret->events[events->size]=hold_event;
	}

	assert(events->size==0);
	free(events);

	return ret;
}
struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *granted,struct AST *statement)
{
	struct AST_Transition *ret;
	ret=malloc(sizeof(struct AST_Transition));
	ret->type=AST_TYPE_TRANSITION;
	ret->from=from;
	ret->to=to;
	ret->event=event;
	ret->granted=granted;
	ret->statement=statement;

	return ret;
}
struct AST_Command* get_ast_command(struct token *function_name,struct token *argument)
{
	struct AST_Command *ret;
	ret=malloc(sizeof(struct AST_Command));
	ret->type=AST_TYPE_COMMAND;
	ret->function_name=function_name;
	ret->argument=argument;

	return ret;
}
struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline)
{
	struct AST_Pipeline *ret;

	ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size]));
	ret->type=AST_TYPE_PIPELINE;
	ret->size=pipeline->size;
	pointer_array_fill((void**)ret->pipeline,pipeline);

	assert(pipeline->size==0);
	free(pipeline);

	return ret;
}
struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state)
{
	struct AST_Machine *ret;

	ret=malloc(sizeof(struct AST_Machine));
	ret->type=AST_TYPE_MACHINE;
	ret->id=id;
	ret->states=states;
	ret->events=events;
	ret->transitions=transitions;
	ret->starting_state=starting_state;

	return ret;
}
struct AST_Transitions* get_ast_transitions(struct Queue *transitions)
{
	struct AST_Transitions *ret;
	ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size]));
	ret->type=AST_TYPE_TRANSITIONS;
	ret->size=transitions->size;

	pointer_array_fill((void**)ret->transitions,transitions);

	assert(transitions->size==0);
	free(transitions);

	return ret;
}
void delete_ast(struct AST* ast)
{
	switch(ast->type)
	{
		case AST_TYPE_MACHINE:
			delete_ast_machine((struct AST_Machine*)ast);
			break;
		case AST_TYPE_STATE:
			delete_ast_state((struct AST_State*)ast);
			break;
		case AST_TYPE_STATES:
			delete_ast_states((struct AST_States*)ast);
			break;
		case AST_TYPE_EVENT:
			delete_ast_event((struct AST_Event*)ast);
			break;
		case AST_TYPE_EVENTS:
			delete_ast_events((struct AST_Events*)ast);
			break;
		case AST_TYPE_TRANSITION:
			delete_ast_transition((struct AST_Transition*)ast);
			break;
		case AST_TYPE_TRANSITIONS:
			delete_ast_transitions((struct AST_Transitions*)ast);
			break;
		case AST_TYPE_COMMAND:
			delete_ast_command((struct AST_Command*)ast);
			break;
		case AST_TYPE_PIPELINE:
			delete_ast_pipeline((struct AST_Pipeline*)ast);
			break;
		case AST_TYPE_TRANSLATION_UNIT:
			delete_ast_translation_unit((struct AST_Translation_Unit*)ast);
			break;
		case AST_TYPE_OP_AND:
		case AST_TYPE_OP_OR:
		case AST_TYPE_OP_SELECTOR:
			delete_ast_binary_expression((struct AST_Binary_Expression*)ast);
			break;
		case AST_TYPE_OP_NOT:
			delete_ast_unary_expression((struct AST_Unary_Expression*)ast);
			break;
		case AST_TYPE_UNFINISHED_STATE:
			delete_ast_unchecked_state((struct AST_Unchecked_State*)ast);
			break;
		case AST_TYPE_IF:
			delete_ast_if_statement((struct AST_If_Statement*)ast);
			break;
	}
}
void delete_ast_event(struct AST_Event* ast)
{
	if(ast==NULL)return;
	delete_token(ast->name);
	free(ast);
}
void delete_ast_states(struct AST_States* ast)
{
	size_t i;
	if(ast==NULL)return;
	for(i=0;i<ast->number_of_states;++i)
		delete_ast_state(ast->states[i]);
	free(ast);
}
void delete_ast_events(struct AST_Events* ast)
{
	size_t i;
	if(ast==NULL)return;
	for(i=0;i<ast->number_of_events;++i)
		delete_ast_event(ast->events[i]);
	free(ast);
}
void delete_ast_transition(struct AST_Transition* ast)
{
	if(ast==NULL)return;
	if(ast->statement!=NULL)
		delete_ast(ast->statement);
	free(ast);
}
void delete_ast_command(struct AST_Command* ast)
{
	if(ast==NULL)return;
	delete_token(ast->function_name);
	if(ast->argument!=NULL)
		delete_token(ast->argument);
	free(ast);
}
void delete_ast_pipeline(struct AST_Pipeline* ast)
{
	size_t i;
	if(ast==NULL)return;
	free(ast);
}
void delete_ast_machine(struct AST_Machine* ast)
{
	if(ast==NULL)return;
	if(ast->id!=NULL)
		delete_token(ast->id);
	if(ast->states!=NULL)
		delete_ast_states(ast->states);
	if(ast->events!=NULL)
		delete_ast_events(ast->events);
	if(ast->transitions!=NULL)
		delete_ast_transitions(ast->transitions);
}
void delete_ast_transitions(struct AST_Transitions* ast)
{
	size_t i;
	if(ast==NULL)return;
	for(i=0;i<ast->size;++i)
		delete_ast_transition(ast->transitions[i]);
	free(ast);
}
void delete_ast_state(struct AST_State* ast)
{
	if(ast==NULL)return;
	if(ast->name!=NULL)
		delete_token(ast->name);
	free(ast);
}
void pointer_array_fill(void **array,struct Queue *q)
{
	size_t i;
	for(i=0;q->size>0;++i)
		array[i]=Queue_Pop(q);
}

struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim)
{
	struct Queue *q;
	struct AST* hold_ast;

	q=malloc(sizeof(struct Queue));
	Queue_Init(q);
	while(hold_ast=parser(translation_data))
	{
		Queue_Push(q,hold_ast);
		if(!get_and_check(translation_data,delim))
			break;
	}
	return q;
}

void delete_ast_translation_unit(struct AST_Translation_Unit *ast)
{
	size_t i;
	Map_Map(ast->used_commands_map,(void (*)(void*))delete_ast_command);
	Map_Destroy(ast->used_commands_map);
	for(i=0;i<ast->number_of_machines;++i)
	{
		delete_ast_machine(ast->machines[i]);
	}
	free(ast->used_commands_map);
	free(ast);
}
struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map)
{
	struct AST_Translation_Unit *ret;
	struct AST_Machine *hold_machine;

	ret=malloc(sizeof(struct AST_Translation_Unit)+sizeof(struct AST_Machine *[machines->size]));
	ret->type=AST_TYPE_TRANSLATION_UNIT;
	ret->used_commands_map=command_map;
	ret->machines_map=machines_map;
	ret->number_of_machines=machines->size;

	while(machines->size>0)
	{
		hold_machine=Queue_Pop(machines);
		ret->machines[machines->size]=hold_machine;
	}

	return ret;
}
/*
 * expression: or-expression
 */
struct AST* parse_expression(struct Translation_Data *translation_data)
{
	return parse_or_expression(translation_data);
}
/*
 * or-expression: and-expression [ || and-expression ]
 */
struct AST* parse_or_expression(struct Translation_Data *translation_data)
{
	struct AST *hold_left_expression;
	struct AST *hold_right_expression;

	hold_left_expression=parse_and_expression(translation_data);
	if(hold_left_expression==NULL)
		return NULL;

	if(get_and_check(translation_data,KW_OR))
	{
		hold_right_expression=parse_and_expression(translation_data);
		if(hold_right_expression==NULL)
		{
			push_parsing_error("expected expression in right side of ||",translation_data);
			delete_ast(hold_left_expression);
			return NULL;
		}
		return (struct AST*)get_ast_binary_expression(hold_left_expression,hold_right_expression,AST_TYPE_OP_OR);
	}else
	{
		return hold_left_expression;
	}

}
/*
 * and-expression: not-expression [ && not-expression ]
 */
struct AST* parse_and_expression(struct Translation_Data *translation_data)
{
	struct AST *hold_left_expression;
	struct AST *hold_right_expression;

	hold_left_expression=parse_not_expression(translation_data);
	if(hold_left_expression==NULL)
		return NULL;

	if(get_and_check(translation_data,KW_AND))
	{
		hold_right_expression=parse_not_expression(translation_data);
		if(hold_right_expression==NULL)
		{
			push_parsing_error("expected expression in right side of &&",translation_data);
			delete_ast(hold_left_expression);
			return NULL;
		}
		return (struct AST*)get_ast_binary_expression(hold_left_expression,hold_right_expression,AST_TYPE_OP_AND);
	}else
	{
		return hold_left_expression;
	}
}
/*
 * not-expression: [!]primary-expression
 */
struct AST* parse_not_expression(struct Translation_Data *translation_data)
{
	struct AST *hold_expression;
	if(get_and_check(translation_data,KW_NOT))
	{
		hold_expression=parse_primary_expression(translation_data);
		if(hold_expression!=NULL)
		{
			return (struct AST*)get_ast_unary_expression(hold_expression,AST_TYPE_OP_NOT);
		}else
		{
			push_parsing_error("in '!' expression",translation_data);
			return NULL;
		}
	}
		return parse_primary_expression(translation_data);
}
/*
 * primary-expression: (expression) | id.id
 */
struct AST* parse_primary_expression(struct Translation_Data *translation_data)
{
	struct AST *hold_expression;
	struct AST_Unchecked_State *hold_id1;
	struct AST_Unchecked_State *hold_id2; 

	if(get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		hold_expression=parse_expression(translation_data);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			return hold_expression;
		}else
		{
			push_parsing_error("expected ')' in expression",translation_data);
			delete_ast(hold_expression);
			return NULL;
		}

	}else if(get_kw(translation_data)==KW_ID)
	{
		hold_id1=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
		if(get_and_check(translation_data,KW_DOT))
		{
			if(get_kw(translation_data)==KW_ID)
			{
				hold_id2=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
				return (struct AST*)get_ast_binary_expression((struct AST*)hold_id1,(struct AST*)hold_id2,AST_TYPE_OP_SELECTOR);
			}else
			{
				push_parsing_error("expected a state id in selector",translation_data);
				delete_ast((struct AST*)hold_id1);
				return NULL;
			}	
		}else
		{
			delete_ast((struct AST*)hold_id1);
			push_parsing_error("expected a selector",translation_data);
			return NULL;
		}
	}else
	{
		push_parsing_error("expected an expression",translation_data);
		return NULL;
	}
}
struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type)
{
	struct AST_Binary_Expression *ret;

	ret=malloc(sizeof(struct AST_Binary_Expression));
	ret->type=type;
	ret->left=left;
	ret->right=right;

	return ret;
}
struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type)
{

	struct AST_Unary_Expression *ret;

	ret=malloc(sizeof(struct AST_Unary_Expression));	

	ret->type=type;
	ret->operand=operand;

	return ret;
}
struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name)
{
	struct AST_Unchecked_State *ret;

	ret=malloc(sizeof(struct AST_Unchecked_State));
	ret->type=AST_TYPE_UNFINISHED_STATE;
	ret->name=name;

	return ret;
}
struct AST_If_Statement* get_ast_if_statement(struct AST *condition,struct AST *body,struct AST *else_statement)
{
	struct AST_If_Statement *ret;

	ret=malloc(sizeof(struct AST_If_Statement));
	ret->type=AST_TYPE_IF;
	ret->condition=condition;
	ret->body=body;
	ret->else_statement=else_statement;

	return ret;
}

struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data)
{
	struct AST_State *ret;
	ret=Map_Check(states->states_map,state->name->data,state->name->size);
	if(ret==NULL)
	{
		push_error_with_token("undefined state",state->name,translation_data);
		delete_ast_unchecked_state(state);
		return NULL;
	}else
	{
		delete_ast_unchecked_state(state);
		return ret;	
	}
}

void delete_ast_binary_expression(struct AST_Binary_Expression *ast)
{
	if(ast->right)
		delete_ast(ast->right);
	if(ast->left)
		delete_ast(ast->left);
	free(ast);
}
void delete_ast_unary_expression(struct AST_Unary_Expression *ast)
{
	if(ast->operand)
		delete_ast(ast->operand);
	free(ast);
}
void delete_ast_unchecked_state(struct AST_Unchecked_State *ast)
{
	delete_token(ast->name);
	free(ast);
}
void delete_ast_if_statement(struct AST_If_Statement *ast)
{
	delete_ast(ast->condition);
	delete_ast(ast->body);
	if(ast->else_statement)
		delete_ast(ast->else_statement);
}
#endif