WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_PARSE_EXPR_C
#define WONKY_PARSE_EXPR_C WONKY_PARSE_EXPR_C
#include "parse_expression.h"



struct AST* parse_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	return (struct AST*)parse_comma_expression(translation_data,scope);
}

struct AST_Expression* parse_const_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	return parse_comma_expression(translation_data,scope);
}
/*
primary-expression:
	number
	string
	id
	(e)
	generic-selection

*/
struct AST_Expression* parse_primary_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct token *hold_token;
	struct AST_Expression *hold;
	
	if(translation_eof(translation_data))
	{
		push_translation_error("expected something here",translation_data);
		return (struct AST_Expression*)get_error_tree(NULL);
	}
	hold_token=get_next_token(translation_data);
	switch(hold_token->type) 
	{
		case KW_STRING:
		case KW_WIDE_STRING:
			return (struct AST_Expression*)get_string_literal_tree(get_expression_value_constant(((struct token_string*)hold_token)->constant));
		case KW_CONSTANT:
			return (struct AST_Expression*)get_constant_tree(get_expression_value_constant(((struct token_constant*)hold_token)->constant));
		case KW_ID:
			return (struct AST_Expression*)get_designator_tree((struct token_identifier*)hold_token,scope,translation_data);
		case KW_OPEN_NORMAL:
			hold=(struct AST_Expression*)parse_expression(translation_data,scope);
			if(get_and_check(translation_data,KW_CLOSE_NORMAL))
			{
				return (struct AST_Expression*)hold;
			}else
			{
				/*TODO error*/
				push_translation_error("expected ')' here",translation_data);
				return (struct AST_Expression*)get_error_tree((struct AST*)hold);
			}
		default:
			/*TODO error*/
			push_translation_error("error in expression",translation_data);
			return (struct AST_Expression*)get_error_tree(NULL);
	}

	/*just in case*/
	wonky_assert(SHOULD_NOT_REACH_HERE);
	return (struct AST_Expression*)get_error_tree(NULL);

}


/*
arglist:
	(e)*\)
	
*/
struct AST_Function_Expression* parse_arglist(struct Translation_Data *translation_data,struct Scope *scope,struct AST_Expression* id)
{
	struct AST_Function_Expression *ret;
	struct AST_Expression *hold_expression;
	struct Queue arg_list;

	Queue_Init(&arg_list);

	if(get_and_check(translation_data,KW_CLOSE_NORMAL))
	{
		return get_function_expression_tree(id,&arg_list,translation_data);
	}

	do
	{
		hold_expression=parse_assignment_expression(translation_data,scope);
		Queue_Push(&arg_list,hold_expression);
	}while(get_and_check(translation_data,KW_COMMA));

	ret=get_function_expression_tree(id,&arg_list,translation_data);
	wonky_assert(arg_list.size==0);

	if(get_and_check(translation_data,KW_CLOSE_NORMAL))
	{
		wonky_assert(is_valid_ast((struct AST*)ret));
		return ret;
	}else
	{
		push_translation_error("expected ')' here",translation_data);
		return (struct AST_Function_Expression*)get_error_tree((struct AST*)ret);
	}

}

/*
postfix_expression:
	postfix_expression ++
	postfix_expression --
	postfix_expression [ expression ]
	postfix_expression.id
	postfix_expression->id
	postfix_expression ( arglist )


	primary_expression
postfix_expression:
	primary_expression ( ++ | -- | \[ expression \] | .id | ->id | \( arglist \) )*

*/
struct AST_Expression* parse_postfix_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_postfix_expression;
	struct AST_Expression *hold_second_expr;

	
	hold_postfix_expression=parse_primary_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_postfix_expression));

		switch(kw_get(translation_data))
		{
			case KW_PLUSPLUS:
				chomp(translation_data);
				hold_postfix_expression=(struct AST_Expression*)get_postfix_inc_dec_tree(hold_postfix_expression,OP_POSTFIX_INC,translation_data);
				break;
			case KW_MINUSMINUS:
				chomp(translation_data);
				hold_postfix_expression=(struct AST_Expression*)get_postfix_inc_dec_tree(hold_postfix_expression,OP_POSTFIX_DEC,translation_data);
				break;
			case KW_DOT:
				chomp(translation_data);
				if(check(translation_data,KW_ID))
				{
					struct identifier *id;
					id=((struct token_identifier*)get_next_token(translation_data))->id;
					hold_postfix_expression=(struct AST_Expression*)get_struct_union_member_tree(hold_postfix_expression,id,translation_data);
				}
				break;
			case KW_ARROW:
				chomp(translation_data);
				if(check(translation_data,KW_ID))
				{
					struct identifier *id;
					id=((struct token_identifier*)get_next_token(translation_data))->id;
					hold_postfix_expression=(struct AST_Expression*)get_struct_union_member_trough_ptr_tree(hold_postfix_expression,id,translation_data);
				}
				break;
			case KW_OPEN_SQUARE:

				chomp(translation_data);
				if(get_and_check(translation_data,KW_CLOSE_SQUARE))
				{
					hold_postfix_expression=(struct AST_Expression*)get_array_subscript_tree(hold_postfix_expression,NULL,translation_data);
				}else
				{
					hold_second_expr=(struct AST_Expression*)parse_expression(translation_data,scope);
					hold_postfix_expression=(struct AST_Expression*)get_array_subscript_tree(hold_postfix_expression,hold_second_expr,translation_data);
					if(!get_and_check(translation_data,KW_CLOSE_SQUARE))
					{
						push_translation_error("expected ']' here",translation_data);
						return (struct AST_Expression*)get_error_tree((struct AST*)hold_postfix_expression);
					}
				}
				break;
			case KW_OPEN_NORMAL:
				chomp(translation_data);
				return (struct AST_Expression*)parse_arglist(translation_data,scope,hold_postfix_expression);
				break;

			default:
				return hold_postfix_expression;
		}
	}

	return hold_postfix_expression;
}

/*
	cast-expression:
		unary-expression
		(type)cast-expression
*/
struct AST_Expression* parse_cast_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Unary_Expression *ret;
	if(check(translation_data,KW_OPEN_NORMAL) && is_type_name(translation_data,scope))
	{
		struct Type *cast_type;
		struct AST_Expression *operand;

		chomp(translation_data);
		cast_type=parse_type_name(translation_data,scope);
		if(get_and_check(translation_data,KW_CLOSE_NORMAL))
		{
			operand=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*)get_cast_expression_tree(operand,cast_type,translation_data);
		}else
		{
			push_translation_error("expected ')' here",translation_data);
			return (struct AST_Expression*)get_error_tree((struct AST*)operand);

		}
	}else
	{
		return parse_unary_expression(translation_data,scope);
	}
}
/*
unary-expression:
	++unary-expression
	--unary-expression
	+unary-expression
	-unary-expression
	!cast-expression
	~cast-expression
	*cast-expression
	&cast-expression
	sizeof ( typename )
	sizeof unary-expression
	postfix-expression

*/

struct AST_Expression* parse_unary_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_expression;
	enum AST_Type operation_type;

	if(translation_eof(translation_data))
	{
		/*TODO error*/
		push_translation_error("expected something here",translation_data);
		return (struct AST_Expression*)get_error_tree(NULL);
	}

	/*TODO make it iterative*/
	switch(kw_get(translation_data))
	{
		case KW_PLUSPLUS:
			chomp(translation_data); hold_expression=parse_unary_expression(translation_data,scope);
			return (struct AST_Expression*)get_prefix_inc_dec_tree(hold_expression,OP_PREFIX_INC,translation_data);
		case KW_MINUSMINUS:
			chomp(translation_data); hold_expression=parse_unary_expression(translation_data,scope);
			return (struct AST_Expression*)get_prefix_inc_dec_tree(hold_expression,OP_PREFIX_DEC,translation_data);
		case KW_PLUS:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*)get_unary_plus_minus_expression(hold_expression,OP_UNARY_PLUS,translation_data);
		case KW_MINUS:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*)get_unary_plus_minus_expression(hold_expression,OP_UNARY_MINUS,translation_data);
		case KW_EXCLAMATION:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*) get_unary_logical_not_expression(hold_expression,translation_data);
		case KW_TILDE:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*) get_unary_bitwise_not_expression(hold_expression,translation_data);
		case KW_STAR:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*) get_indirection_expression_tree(hold_expression,translation_data);
		case KW_AND:
			chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
			return (struct AST_Expression*) get_address_expression_tree(hold_expression,translation_data);
		case KW_SIZEOF:
			chomp(translation_data);
			if(get_and_check(translation_data,KW_OPEN_NORMAL))
			{
				return (struct AST_Expression*)get_sizeof_by_type_tree(parse_type_name(translation_data,scope));
			}else
			{
				hold_expression=parse_unary_expression(translation_data,scope);
				return (struct AST_Expression*)get_unary_sizeof_tree(hold_expression,translation_data); 
			}
		default:
			return parse_postfix_expression(translation_data,scope);
	}
	wonky_assert(SHOULD_NOT_REACH_HERE);
	/*shouldn't reach here - the default of the switch returns*/
}
/*
multiplicative-expression:
	cast-expression ( ( * | / | % ) cast-expression )*
*/
struct AST_Expression* parse_multiplicative_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	hold_left_expression=parse_cast_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));

		switch(kw_get(translation_data))
		{
			case KW_STAR:
				operation_type=OP_MUL;
				break;
			case KW_FORWARD_SLASH:
				operation_type=OP_DIV;
				break;
			case KW_PERCENT:
				operation_type=OP_DIV;
				break;
			default:
				return hold_left_expression; /*BEWARE*/
		}

		chomp(translation_data);
		hold_right_expression=parse_cast_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_multiplicative_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
	}

	return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
additive-expression:
	multiplicative-expression ( ( + | - ) multiplicative )*
*/
struct AST_Expression* parse_additive_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	hold_left_expression=parse_multiplicative_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		switch(kw_get(translation_data))
		{
			case KW_PLUS:
				operation_type=OP_ADDITION;
				break;
			case KW_MINUS:
				operation_type=OP_SUBTRACTION;
				break;
			default:
				return hold_left_expression; /*BEWARE*/
		}

		chomp(translation_data);
		hold_right_expression=parse_multiplicative_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_additive_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);

	}

	return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
bitwise-shift:
	additive-expression ( ( << | >> ) additive-expression)*
*/
struct AST_Expression* parse_shift_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	hold_left_expression=parse_additive_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		switch(kw_get(translation_data))
		{
			case KW_SHIFT_LEFT:
				operation_type=OP_SHIFT_LEFT;
				break;
			case KW_SHIFT_RIGHT:
				operation_type=OP_SHIFT_RIGHT;
				break;
			default:
				return hold_left_expression; /*BEWARE*/
		}
		chomp(translation_data);
		hold_right_expression=parse_additive_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_shift_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
	}
	return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}

/*
relational-expression:
	shift-expression ( ( < | > | <= | >= ) shift-expression )*
*/

struct AST_Expression* parse_relational_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	hold_left_expression=parse_shift_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		switch(kw_get(translation_data))
		{
			case KW_LESS:
				operation_type=OP_LESS;
				break;
			case KW_LESS_EQ:
				operation_type=OP_LESS_EQ;
				break;
			case KW_MORE:
				operation_type=OP_GREATER;
				break;
			case KW_MORE_EQ:
				operation_type=OP_GREATER_EQ;
				break;
			default:
				return hold_left_expression; /*BEWARE*/
		}
		chomp(translation_data);

		hold_right_expression=parse_shift_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_relation_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
	}
	return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}


/*
equality-expression:
	realtional-expression ( ( == | != ) relational-expression )*
*/
struct AST_Expression* parse_equality_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	hold_left_expression=parse_relational_expression(translation_data,scope);

	while(!translation_eof(translation_data))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		switch(kw_get(translation_data))
		{
			case KW_EQEQ:
				operation_type=OP_EQUAL;
				break;
			case KW_NOT_EQ:
				operation_type=OP_NOT_EQUAL;
				break;
			default:
				return hold_left_expression; /*BEWARE*/
		}
		chomp(translation_data);
		hold_right_expression=parse_relational_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_equality_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
	}
	return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
and-expression:
	equality-expression ( & equality-expression ) *
*/
struct AST_Expression* parse_and_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_equality_expression(translation_data,scope);

	while(get_and_check(translation_data,KW_AND))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		hold_right_expression=parse_equality_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_AND,translation_data);
	}
	return hold_left_expression;
}
/*
exclusive-or-expression:
	and-expression (^ and-expression)*

*/
struct AST_Expression* parse_exclusive_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_and_expression(translation_data,scope);

	while(get_and_check(translation_data,KW_HAT))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));
		hold_right_expression=parse_and_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_XOR,translation_data);
	}
	return hold_left_expression;
}
/*
inclusive-or-expression:
	exclusive-or-expression (|exclusive-or-expression)*
*/
struct AST_Expression* parse_inclusive_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_exclusive_or_expression(translation_data,scope);

	while(get_and_check(translation_data,KW_PIPE))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));

		hold_right_expression=parse_exclusive_or_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_OR,translation_data);
	}
	return hold_left_expression;
}
/*
logical-and-expression:
	inclusive-or-expression(&&inclusive-or-expression)*
*/
struct AST_Expression* parse_logical_and_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_inclusive_or_expression(translation_data,scope);

	while(get_and_check(translation_data,KW_AND_AND))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));

		hold_right_expression=parse_inclusive_or_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_logical_expression_tree(hold_left_expression,hold_right_expression,OP_LOGICAL_AND,translation_data);
	}
	return hold_left_expression;
}
/*
logical-or-expression:
	logical-and-expression ( || logical-and-expression )*
*/
struct AST_Expression* parse_logical_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_logical_and_expression(translation_data,scope);

	while(get_and_check(translation_data,KW_PIPE_PIPE))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));

		hold_right_expression=parse_logical_and_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_logical_expression_tree(hold_left_expression,hold_right_expression,OP_LOGICAL_OR,translation_data);
	}
	return hold_left_expression;
}

/*
conditional-expression:
	logical-or-expression
	logical-or-expression?expression:conditional-expression
*/
struct AST_Expression* parse_conditional_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_center_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_logical_or_expression(translation_data,scope);

	wonky_assert(is_valid_ast_expression(hold_left_expression));

	if(get_and_check(translation_data,KW_QUESTION))
	{
		hold_center_expression=(struct AST_Expression*)parse_expression(translation_data,scope);
		if(get_and_check(translation_data,KW_COLUMN))
		{
			hold_right_expression=parse_conditional_expression(translation_data,scope);
		}else
		{
			push_translation_error("expected ':' here",translation_data);
			hold_right_expression=(struct AST_Expression*)get_error_tree(NULL);
		}
		return (struct AST_Expression*)get_conditional_expression_tree(hold_left_expression,hold_center_expression,hold_right_expression,translation_data);
	}else
	{
		return hold_left_expression;
	}
}
/*
assignment-expression:
	conditional-expression
	unary-expression ( ( = | += | -= | %= | /= | *= | >>= | <<= | &= | |= | ^= ) assignment-expression
*/
struct AST_Expression* parse_assignment_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;
	enum AST_Type operation_type;

	if(translation_eof(translation_data))
	{
		push_translation_error("expected something here",translation_data);
		return (struct AST_Expression*)get_error_tree(NULL);
	}

	hold_left_expression=parse_conditional_expression(translation_data,scope);

	wonky_assert(is_valid_ast_expression(hold_left_expression));

	if(translation_eof(translation_data))
		return hold_left_expression;

	/*TODO make it iterative*/
	switch(kw_get(translation_data))
	{
		case KW_EQ:
			operation_type=OP_ASSIGN;
			break;
		case KW_PLUS_EQ:
			operation_type=OP_ADD_ASSIGN;
			break;
		case KW_MINUS_EQ:
			operation_type=OP_SUBTRACT_ASSIGN;
			break;
		case KW_PERCENT_EQ:
			operation_type=OP_REMAINDER_ASSIGN;
			break;
		case KW_DIV_EQ:
			operation_type=OP_DIV_ASSIGN;
			break;
		case KW_STAR_EQ:
			operation_type=OP_MULTIPLY_ASSIGN;
			break;
		case KW_SHIFT_RIGHT_EQ:
			operation_type=OP_SHIFT_RIGHT_ASSIGN;
			break;
		case KW_SHIFT_LEFT_EQ:
			operation_type=OP_SHIFT_LEFT_ASSIGN;
			break;
		case KW_AND_EQ:
			operation_type=OP_AND_ASSIGN;
			break;
		case KW_PIPE_EQ:
			operation_type=OP_PIPE_ASSIGN;
			break;
		case KW_HAT_EQ:
			operation_type=OP_XOR_ASSIGN;
			break;
		default:
			return hold_left_expression; /*BEWARE*/
	}

	chomp(translation_data);
	hold_right_expression=parse_assignment_expression(translation_data,scope);

	wonky_assert(is_valid_ast_expression(hold_right_expression));

	if(operation_type==OP_ASSIGN)
		return (struct AST_Expression*)get_simple_assignment_expression_tree(hold_left_expression,hold_right_expression,translation_data);
	else
		return (struct AST_Expression*)get_compound_assignment_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);

}
/*
comma-expression:
	assignment-expression(,assignment-expression)*
*/
struct AST_Expression* parse_comma_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Expression *hold_left_expression;
	struct AST_Expression *hold_right_expression;

	hold_left_expression=parse_assignment_expression(translation_data,scope);


	while(get_and_check(translation_data,KW_COMMA))
	{
		wonky_assert(is_valid_ast_expression(hold_left_expression));

		hold_right_expression=parse_assignment_expression(translation_data,scope);
		hold_left_expression=(struct AST_Expression*)get_comma_expression_tree(hold_left_expression,hold_right_expression,translation_data);
	}
	return hold_left_expression;
}

#endif