#ifndef WONKY_DEBUG_AST_C
#define WONKY_DEBUG_AST_C WONKY_DEBUG_AST_C
#include <debug_ast.h>
typedef _Bool (*debug_ast_function_ptr)(void*);
static debug_ast_function_ptr debug_ast_vector[AST_TYPE_END+1]=
{
[OP_COMMA]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_POINTER_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SUBTRACTION]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_MUL]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_DIV]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_REMAINDER]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_COND]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_FUNCTION]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_ADD_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SUBTRACT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_MULTIPLY_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_REMAINDER_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_DIV_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SHIFT_RIGHT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SHIFT_LEFT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_AND_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_XOR_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_PIPE_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_NOP]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_LOGICAL_OR]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_LOGICAL_AND]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_LOGICAL_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_BITWISE_OR]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_BITWISE_AND]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_BITWISE_XOR]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_BITWISE_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_ADDR_OF]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_DEREFERENCE]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_MEMBER_TROUGH_PTR]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_MEMBER]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_ARR_SUBSCRIPT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_POSTFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_POSTFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_PREFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_PREFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_UNARY_PLUS]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_UNARY_MINUS]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_CAST]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SIZEOF]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SHIFT_LEFT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_SHIFT_RIGHT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_LESS_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_GREATER_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_LESS]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_GREATER]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_NOT_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_DESIGNATOR]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_CONSTANT]=(debug_ast_function_ptr)is_valid_ast_expression,
[OP_STRING_LITERAL]=(debug_ast_function_ptr)is_valid_ast_expression,
[ST_COMPOUND]=(debug_ast_function_ptr)is_valid_compound_statement,
[ST_EXPRESSION]=(debug_ast_function_ptr)is_valid_ast_expression,
[ST_SWITCH]=(debug_ast_function_ptr)is_valid_switch_statement,
[ST_IF]=(debug_ast_function_ptr)is_valid_if_statement,
[ST_WHILE]=(debug_ast_function_ptr)is_valid_while_statement,
[ST_DO_WHILE]=(debug_ast_function_ptr)is_valid_do_while_statement,
[ST_GOTO]=(debug_ast_function_ptr)is_valid_goto_statement,
[ST_LABEL]=(debug_ast_function_ptr)is_valid_labeled_statement,
[ST_CASE]=(debug_ast_function_ptr)is_valid_case_statement,
[ST_DEFAULT]=(debug_ast_function_ptr)is_valid_default_statement,
[ST_CONTINUE]=(debug_ast_function_ptr)is_valid_break_continue_statement,
[ST_BREAK]=(debug_ast_function_ptr)is_valid_break_continue_statement,
[ST_RETURN]=(debug_ast_function_ptr)is_valid_return_statement,
[ST_FOR]=(debug_ast_function_ptr)is_valid_for_statement,
[ST_OBJECT_DECLARATION]=(debug_ast_function_ptr)is_valid_object_declaration,
[ST_TYPE_DEFINITION]=(debug_ast_function_ptr)is_valid_type_definition,
[ST_FUNCTION_DEFINITION]=(debug_ast_function_ptr)is_valid_function_definition,
[ST_FUNCTION_DECLARATION]=(debug_ast_function_ptr)is_valid_function_declaration,
[TRANSLATION_UNIT]=(debug_ast_function_ptr)is_valid_translation_unit,
[ERROR_DECLARATION]=(debug_ast_function_ptr)is_valid_ast_error_declaration,
[ERROR]=(debug_ast_function_ptr)is_valid_ast_error,
};
_Bool is_valid_ast_enum(enum AST_Type ast_type)
{
return ast_type>=0 && ast_type<AST_TYPE_END;
}
_Bool is_valid_ast_expression_enum(enum AST_Type ast_type)
{
return (ast_type>AST_TYPE_EXPRESSION_START && ast_type<AST_TYPE_EXPRESSION_END) || ast_type==ERROR;
}
_Bool is_valid_ast(struct AST *ast)
{
if(ast==NULL || !is_valid_ast_enum(ast->type) || debug_ast_vector[ast->type]==NULL)
return 0;
else
return debug_ast_vector[ast->type](ast);
}
_Bool is_valid_ast_expression(struct AST_Expression *expression)
{
if(expression==NULL || !is_valid_ast_expression_enum(expression->type))
return 0;
else
return 1;
}
_Bool is_valid_ast_error(struct AST_Error *error)
{
if(error==NULL || error->type!=ERROR)
{
return 0;
}else
{
if(error->error==NULL || is_valid_ast(error->error))
return 1;
else
return 0;
}
}
_Bool is_valid_ast_error_declaration(struct AST_Declaration_Error *error)
{
if(error==NULL || error->type!=ERROR_DECLARATION)
return 0;
else
{
if(error->error==NULL || is_valid_denoted(error->error))
return 1;
else
return 0;
}
}
_Bool is_valid_binary_expression(struct AST_Binary_Expression *expression)
{
if(expression==NULL || !is_valid_ast_expression_enum(expression->type))
return 0;
else
{
return is_valid_value(expression->value)
&&
is_valid_ast_expression(expression->left)
&&
is_valid_ast_expression(expression->right)
;
}
}
_Bool is_valid_pointer_addition_expression(struct AST_Pointer_Addition_Expression *addition)
{
if(addition==NULL || addition->type!=OP_POINTER_ADDITION)
return 0;
else
{
return is_valid_value(addition->value)
&&
is_valid_ast_expression(addition->pointer)
&&
is_valid_ast_expression(addition->integer)
;
}
}
_Bool is_valid_conditional_expression(struct AST_Conditional_Expression *conditional_expression)
{
if(conditional_expression==NULL || conditional_expression->type!=OP_COND)
return 0;
else
{
return is_valid_value(conditional_expression->value)
&&
is_valid_ast_expression(conditional_expression->left)
&&
is_valid_ast_expression(conditional_expression->center)
&&
is_valid_ast_expression(conditional_expression->right)
;
}
}
_Bool is_valid_function_expression(struct AST_Function_Expression *function_call)
{
if(function_call==NULL || function_call->type!=OP_FUNCTION)
return 0;
else if(!is_valid_ast_expression(function_call->id) || !is_valid_value(function_call->value))
return 0;
else
{
size_t i;
for(i=0;i<function_call->number_of_arguments;++i)
if(!is_valid_ast_expression(function_call->arg_list[i]))
return 0;
return 1;
}
}
_Bool is_valid_ast_constant(struct AST_Constant *constant)
{
if(constant==NULL || constant->type!=OP_CONSTANT)
return 0;
else
return 1;
}
_Bool is_valid_ast_string_literal(struct AST_String_Literal *literal)
{
if(literal==NULL || literal->type!=OP_STRING_LITERAL)
return 0;
else
return 1;
}
_Bool is_valid_ast_designator(struct AST_Designator *designator)
{
if(designator==NULL || designator->type!=OP_DESIGNATOR)
return 0;
else
return is_valid_value(designator->value)
&&
is_valid_id(designator->id)
;
}
_Bool is_valid_unary_expression(struct AST_Unary_Expression *expression)
{
static _Bool unary_expressions[AST_TYPE_END]
=
{
[OP_CAST]=1,
[OP_DEREFERENCE]=1,
[OP_ADDR_OF]=1,
[OP_SIZEOF]=1,
[OP_PREFIX_INC]=1,
[OP_PREFIX_DEC]=1,
[OP_POSTFIX_INC]=1,
[OP_POSTFIX_DEC]=1,
[OP_UNARY_PLUS]=1,
[OP_UNARY_MINUS]=1,
[OP_BITWISE_NOT]=1,
[OP_LOGICAL_NOT]=1,
};
if(expression==NULL || !is_valid_expression_value_type(expression->type) || !unary_expressions[expression->type])
return 0;
else
return is_valid_value(expression->value) && is_valid_ast_expression(expression->operand);
}
_Bool is_valid_labeled_statement(struct AST_Labeled_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
return is_valid_denoted_statement(statement->label);
}
_Bool is_valid_case_statement(struct AST_Case_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
return is_valid_ast(statement->statement) && is_valid_ast_expression(statement->control);
}
_Bool is_valid_default_statement(struct AST_Default_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
return is_valid_ast(statement->statement);
}
_Bool is_valid_break_continue_statement(struct AST_Break_Continue_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
return statement->parent!=NULL; /*we don't check parent*/
}
_Bool is_valid_compound_statement(struct AST_Compound_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
struct Queue_Node *it;
for(it=statement->components->first;it!=NULL;it=it->prev)
if(!is_valid_ast(it->data))
return 0;
return statement->scope!=NULL;
}
}
_Bool is_valid_for_statement(struct AST_For_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
return is_valid_ast(statement->condition)
&&
is_valid_ast(statement->initialisation)
&&
is_valid_ast(statement->update)
&&
is_valid_ast(statement->body_statement)
;
}
}
_Bool is_valid_while_statement(struct AST_While_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
return is_valid_ast(statement->condition)
&&
is_valid_ast(statement->body_statement)
;
}
}
_Bool is_valid_do_while_statement(struct AST_Do_While_Statement *statement)
{
if(statement==NULL || statement->type!=ST_DO_WHILE)
return 0;
else
{
return is_valid_ast(statement->condition)
&&
is_valid_ast(statement->body_statement)
;
}
}
_Bool is_valid_if_statement(struct AST_If_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
if(statement->else_statement!=NULL && !is_valid_ast(statement->else_statement))
return 0;
else
return is_valid_ast(statement->condition)
&&
is_valid_ast(statement->body_statement)
;
}
}
_Bool is_valid_goto_statement(struct AST_Goto_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
if(statement->label!=NULL && !is_valid_denoted_statement(statement->label))
return 0;
if(statement->previous_denoted_object!=NULL && !is_valid_denoted_object(statement->previous_denoted_object))
return 0;
return 1;
}
}
_Bool is_valid_switch_statement(struct AST_Switch_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
{
return is_valid_ast_expression(statement->condition)
&&
is_valid_ast(statement->body_statement);
}
}
_Bool is_valid_return_statement(struct AST_Return_Statement *statement)
{
if(statement==NULL || !is_valid_ast_enum(statement->type))
return 0;
else
return is_valid_ast(statement->return_expression);
}
_Bool is_valid_type_definition(struct AST_Type_Definition *definition)
{
if(definition==NULL || !is_valid_ast_enum(definition->type))
return 0;
else
return is_valid_denoted_type(definition->definition);
}
_Bool is_valid_object_declaration(struct AST_Object_Declaration *declaration)
{
if(declaration==NULL || !is_valid_ast_enum(declaration->type))
return 0;
else
return is_valid_denoted_object(declaration->object) && is_valid_initialiser(declaration->initializer);
}
_Bool is_valid_function_definition(struct AST_Function_Definition *definition)
{
if(definition==NULL || !is_valid_ast_enum(definition->type))
return 0;
else
return is_valid_denoted_function(definition->function) && is_valid_compound_statement(definition->body);
}
_Bool is_valid_function_declaration(struct AST_Function_Declaration *declaration)
{
if(declaration==NULL || !is_valid_ast_enum(declaration->type))
return 0;
else
return is_valid_denoted_function(declaration->function);
}
_Bool is_valid_translation_unit(struct AST_Translation_Unit *unit)
{
if(unit==NULL || !is_valid_ast_enum(unit->type))
return 0;
else
{
struct Queue_Node *it;
for(it=unit->function_definitions->first;it!=NULL;it=it->prev)
if(!is_valid_ast(it->data))
return 0;
if(!is_valid_scope(unit->file_scope))
return 0;
if(!is_valid_linkage(unit->internal_linkage))
return 0;
return 1;
}
}
#endif