WONKY



LOG | FILES | OVERVIEW


#ifndef PARSE_WONKY_STATEMENT_C
#define PARSE_WONKY_STATEMENT_C PARSE_WONKY_STATEMENT_C
#include "parse_statement.h"


struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{

	if(translation_eof(translation_data))
		return NULL;

	switch(kw_get(translation_data))
	{
		case KW_NOTYPE:
			push_translation_error("statement expected",translation_data);
			return (struct AST*)get_error_tree(NULL);
		case KW_OPEN_CURLY:
			chomp(translation_data);
			return parse_finish_compound_statement(translation_data,scope,parse_data);
		case KW_IF:
			chomp(translation_data);
			return parse_finish_if_statement(translation_data,scope,parse_data);
		case KW_SWITCH:
			chomp(translation_data);
			return parse_finish_switch_statement(translation_data,scope,parse_data);
		case KW_WHILE:
			chomp(translation_data);
			return parse_finish_while_statement(translation_data,scope,parse_data);
		case KW_DO:
			chomp(translation_data);
			return parse_finish_do_while_statement(translation_data,scope,parse_data);
		case KW_FOR:
			chomp(translation_data);
			return parse_finish_for_statement(translation_data,scope,parse_data);
		case KW_GOTO:
			chomp(translation_data);
			return parse_finish_goto_statement(translation_data,scope,parse_data);
		case KW_CASE:
			chomp(translation_data);
			return parse_finish_case_statement(translation_data,scope,parse_data);
		case KW_DEFAULT:
			chomp(translation_data);
			return parse_finish_default_statement(translation_data,scope,parse_data);
		case KW_ID:
			{
				struct token_identifier *hold_token;
				hold_token=(struct token_identifier*)get_next_token(translation_data);
				if(check(translation_data,KW_COLUMN))
				{
					token_ptr_unget_token(translation_data->token_pointer,(struct token*)hold_token);
					return parse_finish_labeled_statement(translation_data,scope,parse_data);
				}else
				{
					token_ptr_unget_token(translation_data->token_pointer,(struct token*)hold_token);
					return parse_expression_statement(translation_data,scope,parse_data);
				}
			}
		case KW_CONTINUE:
			chomp(translation_data);
			return parse_finish_continue_statement(translation_data,parse_data);
		case KW_BREAK:
			chomp(translation_data);
			return parse_finish_break_statement(translation_data,parse_data);
		case KW_RETURN:
			chomp(translation_data);
			return parse_finish_return_statement(translation_data,scope,parse_data);
		default:
			return parse_expression_statement(translation_data,scope,parse_data);

	}

}
/*
	( declaration | statement )* }
*/
struct AST* parse_finish_compound_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Compound_Statement *hold;

	hold=get_compound_statement_tree(scope);

	while(!get_and_check(translation_data,KW_CLOSE_CURLY) && !has_no_tokens(translation_data))
	{
		if(is_type_name(translation_data,hold->scope))
			parse_declaration(translation_data,hold->scope,hold->components);	
		else
			Queue_Push(hold->components,parse_statement(translation_data,hold->scope,parse_data));

		if(has_new_errors(translation_data))
			chase_next_semicolumn(translation_data);
	}

	wonky_assert(is_valid_compound_statement(hold));
	return (struct AST*)hold;
}
/*
   ( expression ) statement
   ( expression ) statement else statement
*/
struct AST* parse_finish_if_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_If_Statement *hold;
	hold=get_if_statement_tree();
	if(get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		hold->condition=parse_expression(translation_data,scope);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			hold->body_statement=parse_statement(translation_data,scope,parse_data);
		}else
		{
			push_translation_error(" ')' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)hold);
		}
		if(get_and_check(translation_data,KW_ELSE)) 
		{
			hold->else_statement=parse_statement(translation_data,scope,parse_data);
			return (struct AST*)hold;
		}else
		{
			hold->else_statement=NULL;
			return (struct AST*)hold;
		}
	}else
	{
		push_translation_error(" '(' expected",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold);
	}

	wonky_assert(is_valid_if_statement(hold));
	return (struct AST*)hold;
}
/*
	( expression ) statement
*/
struct AST* parse_finish_switch_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Switch_Statement *hold;
	struct AST_Expression *hold_control_expression;
	struct AST *hold_body_statement;

	if(get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		hold_control_expression=(struct AST_Expression*)parse_expression(translation_data,scope);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			hold_body_statement
				=
				parse_statement(
						translation_data,
						scope,
						&(struct Parse_Statement_Data)
						{
							.break_statement_owner=(struct AST*)hold,
							.continue_statement_owner=parse_data->continue_statement_owner,
							.current_switch_statement=hold,
						}
					);

			hold=get_switch_statement_tree(hold_control_expression,hold_body_statement);

			wonky_assert(is_valid_switch_statement(hold));
			return (struct AST*)hold;
		}else
		{
			push_translation_error(" ')' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)hold_control_expression);
		}
	}else
	{
		push_translation_error(" '(' expected",translation_data);
		return (struct AST*)get_error_tree((struct AST*)NULL);
	}

	wonky_assert(SHOULD_NOT_REACH_HERE);
}
/*
 	( expression ) statement

*/
struct AST* parse_finish_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_While_Statement *hold;
	hold=get_while_statement_tree();
	if(get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		hold->condition=parse_expression(translation_data,scope);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			hold->body_statement
				=
				parse_statement(
						translation_data,
						scope,
						&(struct Parse_Statement_Data)
						{
							.break_statement_owner=(struct AST*)hold,
							.continue_statement_owner=(struct AST*)hold,
							.current_switch_statement=parse_data->current_switch_statement,
						}
					);

			wonky_assert(is_valid_while_statement(hold));
			return (struct AST*)hold;
		}else
		{
			push_translation_error(" ')' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)hold);
		}
	}else
	{
		push_translation_error(" '(' expected",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold);
	}

	wonky_assert(SHOULD_NOT_REACH_HERE);

}
/*
	statement while ( expression ) ;
*/
struct AST* parse_finish_do_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Do_While_Statement *hold;
	hold=get_do_while_statement_tree();

	hold->body_statement
		=
		parse_statement(
				translation_data,
				scope,
				&(struct Parse_Statement_Data)
				{
					.break_statement_owner=(struct AST*)hold,
					.continue_statement_owner=(struct AST*)hold,
					.current_switch_statement=parse_data->current_switch_statement,
				}
			       );



	if(get_and_check(translation_data,KW_WHILE) && get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		hold->condition=parse_expression(translation_data,scope);

		if(get_and_check(translation_data,KW_CLOSE_NORMAL) && get_and_check(translation_data,KW_SEMICOLON))
		{
			wonky_assert(is_valid_do_while_statement(hold));
			return (struct AST*)hold;
		}else
		{
			push_translation_error(" ';' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)hold);
		}
	}else
	{
		push_translation_error("'do-while' statement is unfinished",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold);
	}

}
/*
	( [ expression ] ; [ expression ] ; [ expression ] ) statement
*/
struct AST* parse_finish_for_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_For_Statement *hold;
	hold=get_for_statement_tree();
	if(!get_and_check(translation_data,KW_OPEN_NORMAL))
	{
		push_translation_error(" '(' expected",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold);
	}

	hold->initialisation=parse_expression_statement(translation_data,scope,parse_data);
	if(hold->initialisation->type==ERROR)
		push_translation_error("expected expression or declaration in for loop initialisation",translation_data);
		
	hold->condition=parse_expression_statement(translation_data,scope,parse_data);

	if(get_and_check(translation_data,KW_CLOSE_NORMAL))
	{
		hold->update=get_nop_tree();
	}else
	{
		hold->update=parse_expression(translation_data,scope);
		if(!get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			push_translation_error(" ')' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)hold);
		}
	}


	hold->body_statement
		=
		parse_statement(
				translation_data,
				scope,
				&(struct Parse_Statement_Data)
				{
					.break_statement_owner=(struct AST*)hold,
					.continue_statement_owner=(struct AST*)hold,
					.current_switch_statement=parse_data->current_switch_statement,
				}
			       );

	wonky_assert(is_valid_for_statement(hold));
	return (struct AST*)hold;
}
/*
	id ;
*/
struct AST* parse_finish_goto_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Goto_Statement* ret;

	if(check(translation_data,KW_ID))
	{
		struct token_identifier *hold_id_token;
		hold_id_token=(struct token_identifier*)get_next_token(translation_data);
		ret=get_goto_statement_tree(hold_id_token->id,scope,translation_data);
		if(get_and_check(translation_data,KW_SEMICOLON))
		{
			wonky_assert(is_valid_goto_statement(ret));
			return (struct AST*)ret;
		}else
		{
			push_translation_error(" ';' expected",translation_data);
			return (struct AST*)get_error_tree((struct AST*)ret);
		}
	}
	else
	{
		push_translation_error(" label expected in goto statement",translation_data);
		return (struct AST*)get_error_tree(NULL);
	}

}
/*
   ;
*/
struct AST* parse_finish_continue_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data)
{

	struct AST_Break_Continue_Statement *hold;
	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		hold=get_break_continue_statement_tree(parse_data->continue_statement_owner,translation_data,ST_CONTINUE);

		wonky_assert(is_valid_break_continue_statement(hold));
		return (struct AST*)hold;
	}else
	{
		push_translation_error(" ';' expected",translation_data);
		return (struct AST*)get_error_tree(NULL);
	}
}
/*
   ;
*/
struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data)
{
	struct AST_Break_Continue_Statement *hold;

	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		hold=get_break_continue_statement_tree(parse_data->break_statement_owner,translation_data,ST_BREAK);

		wonky_assert(is_valid_break_continue_statement(hold));
		return (struct AST*)hold;
	}else
	{
		push_translation_error(" ';' expected",translation_data);
		return (struct AST*)get_error_tree(NULL);
	}
}
/*
   id:
   statement
*/
struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST *hold_statement;
	struct token_identifier *hold_id;
	struct AST_Labeled_Statement *hold;

	/*id and ':' are checked for in the parse_statement function*/

	hold_id=(struct token_identifier*)get_next_token(translation_data);
	chomp(translation_data); /* ':' */
	hold_statement=parse_statement(translation_data,scope,parse_data);

	hold=get_labeled_statement_tree(hold_id->id,hold_statement,ST_LABEL,translation_data,scope);

	wonky_assert(is_valid_labeled_statement(hold));
	return (struct AST*)hold;
}

/*
	constant-expresssion :
		statement


  */
struct AST* parse_finish_case_statement(struct Translation_Data *translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Expression *hold_expression;
	struct AST *hold_statement;
	struct AST_Case_Statement *hold;

	hold_expression=(struct AST_Expression*)parse_expression(translation_data,scope);

	if(get_and_check(translation_data,KW_COLUMN))
	{
		hold_statement=parse_statement(translation_data,scope,parse_data);
		hold=get_case_statement_tree(hold_statement,hold_expression,parse_data->current_switch_statement,translation_data);

		wonky_assert(is_valid_case_statement(hold));
		return (struct AST*)hold;
	}else
	{
		push_translation_error(" ':' expected after expression in case statement",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold_expression);
	}
	wonky_assert(SHOULD_NOT_REACH_HERE);
}
/*
	:
	statement
   */
struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST *statement;
	struct AST_Default_Statement *hold;

	if(get_and_check(translation_data,KW_COLUMN))
	{
		statement=parse_statement(translation_data,scope,parse_data);

		hold=get_default_statement_tree(statement,translation_data);

		wonky_assert(is_valid_default_statement(hold));
		return (struct AST*)hold;
	}else
	{
		push_translation_error(" ':' expected in default statement",translation_data);
		return (struct AST*)get_error_tree((struct AST*)NULL);
	}
}
/*
	[ expression ] ;

*/
struct AST* parse_finish_return_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST_Return_Statement *hold;
	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		hold=get_return_statement_tree(get_nop_tree(),translation_data,scope);

		wonky_assert(is_valid_return_statement(hold));
		return (struct AST*)hold;
	}


	hold=get_return_statement_tree(parse_expression(translation_data,scope),translation_data,scope);
	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		return (struct AST*)hold;
	}else
	{
		push_translation_error(" ';' expected",translation_data);
		return (struct AST*)get_error_tree((struct AST*)hold);
	}
}
/*
   	
	[ expression ] ;

*/
struct AST* parse_expression_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
	struct AST *hold;
	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		hold=get_nop_tree();
		return (struct AST*)hold;
	}
	hold=parse_expression(translation_data,scope);
	if(hold==NULL)
	{
		push_translation_error(" in statement",translation_data);
		return (struct AST*)get_error_tree(hold);
	}
	if(get_and_check(translation_data,KW_SEMICOLON))
	{
		wonky_assert(is_valid_ast(hold));
		return hold;
	}else
	{
		push_translation_error(" ';' expected",translation_data);
		return (struct AST*)get_error_tree(hold);
	}
}
void chase_next_semicolumn(struct Translation_Data *translation_data)
{
	/*chase ; and start parsing next declaration*/
	while(!get_and_check(translation_data,KW_SEMICOLON) && !get_and_check(translation_data,KW_CLOSE_CURLY) &&
		       	!translation_eof(translation_data))
	{
		chomp(translation_data);
	}
}
#endif