F diff --git a/src/frontend/parse/parse_declaration.c b/src/frontend/parse/parse_declaration.c
--- a/src/frontend/parse/parse_declaration.c
+++ b/src/frontend/parse/parse_declaration.c
function_type->function_prototype_scope->parent=(struct Scope*)hold_function->function_scope;
- hold_function->body=
- (struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,(struct Scope*)function_type->function_prototype_scope,NULL,NULL);
+ hold_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,
+ }
+ );
+
Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold,translation_data));
break;
}
F diff --git a/src/frontend/parse/parse_statement.c b/src/frontend/parse/parse_statement.c
--- a/src/frontend/parse/parse_statement.c
+++ b/src/frontend/parse/parse_statement.c
#include "parse_statement.h"
- struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
if(translation_data->tokens->size==0)
return (struct AST*)get_error_tree(NULL);
case KW_OPEN_CURLY:
chomp(translation_data);
- return parse_finish_compound_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_compound_statement(translation_data,scope,parse_data);
case KW_IF:
chomp(translation_data);
- return parse_finish_if_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_if_statement(translation_data,scope,parse_data);
case KW_SWITCH:
chomp(translation_data);
- return parse_finish_switch_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_switch_statement(translation_data,scope,parse_data);
case KW_WHILE:
chomp(translation_data);
- return parse_finish_while_statement(translation_data,scope,upper_loop,upper_switch);
+ 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,upper_loop,upper_switch);
+ 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,upper_loop,upper_switch);
+ return parse_finish_for_statement(translation_data,scope,parse_data);
case KW_GOTO:
chomp(translation_data);
- return parse_finish_goto_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_goto_statement(translation_data,scope,parse_data);
case KW_CASE:
chomp(translation_data);
- return parse_finish_case_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_case_statement(translation_data,scope,parse_data);
case KW_DEFAULT:
chomp(translation_data);
- return parse_finish_default_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_default_statement(translation_data,scope,parse_data);
case KW_ID:
if(check(translation_data,KW_COLUMN,1))
{
- return parse_finish_labeled_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_labeled_statement(translation_data,scope,parse_data);
}else
{
- return parse_expression_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_expression_statement(translation_data,scope,parse_data);
}
case KW_CONTINUE:
chomp(translation_data);
- return parse_finish_continue_statement(translation_data,upper_loop,upper_switch);
+ return parse_finish_continue_statement(translation_data,parse_data);
case KW_BREAK:
chomp(translation_data);
- return parse_finish_break_statement(translation_data,upper_loop,upper_switch);
+ return parse_finish_break_statement(translation_data,parse_data);
case KW_RETURN:
chomp(translation_data);
- return parse_finish_return_statement(translation_data,scope,upper_loop,upper_switch);
+ return parse_finish_return_statement(translation_data,scope,parse_data);
default:
- return parse_expression_statement(translation_data,scope,upper_loop,upper_switch);
+ 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 AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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);
parse_declaration(translation_data,hold->scope,&hold->components,0);
}else
{
- Queue_Push(&hold->components,parse_statement(translation_data,hold->scope,upper_loop,upper_switch));
+ Queue_Push(&hold->components,parse_statement(translation_data,hold->scope,parse_data));
}
if(has_new_errors(translation_data))
chase_next_semicolumn(translation_data);
( expression ) statement
( expression ) statement else statement
*/
- struct AST* parse_finish_if_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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();
hold->condition=parse_expression(translation_data,scope);
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
- hold->body_statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+ hold->body_statement=parse_statement(translation_data,scope,parse_data);
}else
{
push_translation_error(" ')' expected",translation_data);
}
if(get_and_check(translation_data,KW_ELSE))
{
- hold->else_statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+ hold->else_statement=parse_statement(translation_data,scope,parse_data);
return (struct AST*)hold;
}else
{
/*
( expression ) statement
*/
- struct AST* parse_finish_switch_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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;
- hold=get_switch_statement_tree();
+ struct AST_Expression *hold_control_expression;
+ struct AST *hold_body_statement;
+
if(get_and_check(translation_data,KW_OPEN_NORMAL))
{
- hold->condition=parse_expression(translation_data,scope);
+ 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,upper_loop,hold);
+ 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);
+ return (struct AST*)hold;
}else
{
push_translation_error(" ')' expected",translation_data);
- return (struct AST*)get_error_tree((struct AST*)hold);
+ 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*)hold);
+ return (struct AST*)get_error_tree((struct AST*)NULL);
}
- return (struct AST*)hold;
+ assert(0);
}
/*
( expression ) statement
*/
- struct AST* parse_finish_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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();
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 AST*)hold,upper_switch);
+ 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,
+ }
+ );
+ return (struct AST*)hold;
}else
{
push_translation_error(" ')' expected",translation_data);
return (struct AST*)get_error_tree((struct AST*)hold);
}
- return (struct AST*)hold;
+ assert(0);
+
}
/*
statement while ( expression ) ;
*/
- struct AST* parse_finish_do_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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 AST*)hold,upper_switch);
+
+ 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);
/*
( [ expression ] ; [ expression ] ; [ expression ] ) statement
*/
- struct AST* parse_finish_for_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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();
return (struct AST*)get_error_tree((struct AST*)hold);
}
- hold->initialisation=parse_expression_statement(translation_data,scope,upper_loop,upper_switch);
- hold->condition=parse_expression_statement(translation_data,scope,upper_loop,upper_switch);
+ hold->initialisation=parse_expression_statement(translation_data,scope,parse_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();
return (struct AST*)get_error_tree((struct AST*)hold);
}
}
- hold->body_statement=parse_statement(translation_data,scope,(struct AST*)hold,upper_switch);
+
+
+ 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,
+ }
+ );
+
return (struct AST*)hold;
}
/*
id ;
*/
- struct AST* parse_finish_goto_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_finish_goto_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
struct AST* ret;
/*
;
*/
- struct AST* parse_finish_continue_statement(struct Translation_Data* translation_data,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_finish_continue_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data)
{
- struct AST *hold;
- hold=malloc(sizeof(struct AST));
- hold->type=ST_CONTINUE;
+
if(get_and_check(translation_data,KW_SEMI_COLUMN))
{
- return hold;
+ return (struct AST*)get_break_continue_statement_tree(parse_data->continue_statement_owner,translation_data,ST_CONTINUE);
}else
{
push_translation_error(" ';' expected",translation_data);
- return (struct AST*)get_error_tree(hold);
+ return (struct AST*)get_error_tree(NULL);
}
}
/*
;
*/
- struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data)
{
- struct AST *hold;
- hold=malloc(sizeof(struct AST));
- hold->type=ST_BREAK;
if(get_and_check(translation_data,KW_SEMI_COLUMN))
{
- return hold;
+ return (struct AST*)get_break_continue_statement_tree(parse_data->break_statement_owner,translation_data,ST_BREAK);
}else
{
push_translation_error(" ';' expected",translation_data);
- return (struct AST*)get_error_tree(hold);
+ return (struct AST*)get_error_tree(NULL);
}
}
/*
id:
statement
*/
- struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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 *hold_id;
hold_id=Queue_Pop(translation_data->tokens);
chomp(translation_data); /* ':' */
- hold_statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+ hold_statement=parse_statement(translation_data,scope,parse_data);
return (struct AST*)get_labeled_statement_tree(hold_id,hold_statement,ST_LABEL,translation_data,scope);
}
/*
- constant :
+ constant-expresssion :
statement
*/
- struct AST* parse_finish_case_statement(struct Translation_Data *translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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;
+ 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);
+ return (struct AST*)get_case_statement_tree(hold_statement,hold_expression,parse_data->current_switch_statement,translation_data);
+ }else
+ {
+ push_translation_error(" ':' expected after expression in case statement",translation_data);
+ return (struct AST*)get_error_tree((struct AST*)hold_expression);
+ }
+ assert(0);
}
/*
:
statement
*/
- struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data)
{
struct AST *statement;
if(get_and_check(translation_data,KW_COLUMN))
{
- statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+ statement=parse_statement(translation_data,scope,parse_data);
return (struct AST*)get_default_statement_tree(statement,translation_data);
}else
{
[ expression ] ;
*/
- struct AST* parse_finish_return_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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_SEMI_COLUMN))
[ expression ] ;
*/
- struct AST* parse_expression_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ 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_SEMI_COLUMN))
F diff --git a/src/frontend/parse/parse_statement.h b/src/frontend/parse/parse_statement.h
--- a/src/frontend/parse/parse_statement.h
+++ b/src/frontend/parse/parse_statement.h
#ifndef PARSE_WONKY_STATEMENT_H
#define PARSE_WONKY_STATEMENT_H PARSE_WONKY_STATEMENT_H
+ #include <parse_statement.hh>
#include <scope.h>
#include <ast.h>
#include <queue.h>
#include <program.h>
+ struct Parse_Statement_Data
+ {
+ struct AST *break_statement_owner;
+ struct AST *continue_statement_owner;
+ struct AST_Switch_Statement *current_switch_statement;
+ };
- struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_compound_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_if_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_switch_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_do_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_for_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_goto_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_continue_statement(struct Translation_Data* translation_data,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_return_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_expression_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_case_statement(struct Translation_Data *translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
+ struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_compound_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_if_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_switch_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_do_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_while_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_for_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_goto_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_continue_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_return_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_expression_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+ struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
- struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
+ struct AST* parse_finish_case_statement(struct Translation_Data *translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
+
+ struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct Parse_Statement_Data *parse_data);
void chase_next_semicolumn(struct Translation_Data *translation_data);
F diff --git a/src/frontend/parse/parse_statement.hh b/src/frontend/parse/parse_statement.hh
new file mode 100644
--- /dev/null
+++ b/src/frontend/parse/parse_statement.hh
+ #ifndef PARSE_WONKY_STATEMENT_HH
+ #define PARSE_WONKY_STATEMENT_HH PARSE_WONKY_STATEMENT_HH
+
+ struct Parse_Statement_Data;
+
+ #endif
F diff --git a/src/semantics/ast.c b/src/semantics/ast.c
--- a/src/semantics/ast.c
+++ b/src/semantics/ast.c
}
+ struct AST_Case_Statement* get_case_statement_tree(struct AST *statement,struct AST_Expression *control,struct AST_Switch_Statement *parent,struct Translation_Data *translation_data)
+ {
+ struct AST_Case_Statement *ret;
+ ret=malloc(sizeof(struct AST_Case_Statement));
+
+ ret->type=ST_CASE;
+ ret->control=control;
+ ret->statement=statement;
+
+ if(constraint_check_case_statement(ret,parent,translation_data))
+ return ret;
+ else
+ return (struct AST_Case_Statement*)get_error_tree((struct AST*)ret);
+
+ }
struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Labeled_Statement *ret;
ret=malloc(sizeof(struct AST_Labeled_Statement));
ret->type=type;
-
ret->label=(struct Denoted_Statement*)push_label(scope,label,statement,translation_data);
-
return ret;
}
struct AST_Default_Statement* get_default_statement_tree(struct AST *statement,struct Translation_Data *translation_data)
return ret;
}
+ struct AST_Break_Continue_Statement* get_break_continue_statement_tree(struct AST *parent,struct Translation_Data *translation_data,enum AST_Type break_or_continue)
+ {
+ struct AST_Break_Continue_Statement *ret;
+ ret=malloc(sizeof(struct AST_Break_Continue_Statement));
+ ret->type=break_or_continue;
+ ret->parent=parent;
+ if(constraint_check_break_continue_statement(ret,translation_data))
+ return ret;
+ else
+ return (struct AST_Break_Continue_Statement*)get_error_tree((struct AST*)ret);
+ }
struct AST_Compound_Statement* get_compound_statement_tree(struct Scope *parent_scope)
{
struct AST_Compound_Statement *ret;
return ret;
}
- struct AST_Switch_Statement* get_switch_statement_tree()
+ struct AST_Switch_Statement* get_switch_statement_tree(struct AST_Expression *condidion,struct AST *body_statement)
{
struct AST_Switch_Statement *ret;
+
ret=malloc(sizeof(struct AST_Switch_Statement));
+ ret->cases=malloc(sizeof(struct Queue));
+
+ Queue_Init(ret->cases);
+
ret->type=ST_SWITCH;
+ ret->condition=condidion;
+ ret->body_statement=body_statement;
+
+
+
return ret;
}
struct AST_While_Statement* get_while_statement_tree()
return ret;
}
+ /*
+ * TODO
+ */
+ _Bool ast_is_a_constant_expression(struct AST *ast,struct Translation_Data *translation_data)
+ {
+ return 0;
+ }
void delete_ast(struct AST* ast)
{
delete_ast_goto_statemtent((struct AST_Goto_Statement*)ast);
break;
case ST_LABEL:
- case ST_CASE:
delete_ast_labeled_statement((struct AST_Labeled_Statement*)ast);
break;
+ case ST_CASE:
+ delete_ast_case_statement((struct AST_Case_Statement*)ast);
+ break;
case ST_DEFAULT:
+ delete_ast_default_statement((struct AST_Default_Statement*)ast);
+ break;
case ST_CONTINUE:
case ST_BREAK:
- /*I think it doesnt come with anything*/
- free(ast);
+ delete_ast_break_continue_statement((struct AST_Break_Continue_Statement*)ast);
break;
case ST_RETURN:
delete_ast_return_statement((struct AST_Return_Statement*)ast);
delete_denoted((struct Denoted*)labeled_statement->label);
free(labeled_statement);
}
+ void delete_ast_default_statement(struct AST_Default_Statement *default_statement)
+ {
+ free(default_statement);
+ }
+ void delete_ast_break_continue_statement(struct AST_Break_Continue_Statement *break_continue)
+ {
+ free(break_continue);
+ }
void delete_ast_compound_statement(struct AST_Compound_Statement *compound_statement)
{
if(compound_statement->scope!=NULL)
void delete_ast_switch_statement(struct AST_Switch_Statement *switch_statement)
{
if(switch_statement->condition!=NULL)
- delete_ast(switch_statement->condition);
+ delete_ast((struct AST*)switch_statement->condition);
if(switch_statement->body_statement!=NULL)
delete_ast(switch_statement->body_statement);
+
+ while(switch_statement->cases->size>0)
+ Queue_Pop(switch_statement->cases);
+
+ free(switch_statement->cases);
free(switch_statement);
}
+ void delete_ast_case_statement(struct AST_Case_Statement *case_statement)
+ {
+ if(case_statement->control)
+ delete_ast((struct AST*)case_statement->control);
+ if(case_statement->statement)
+ delete_ast(case_statement->statement);
+ free(case_statement);
+ }
void delete_ast_return_statement(struct AST_Return_Statement *return_statement)
{
if(return_statement->return_expression!=NULL)
F diff --git a/src/semantics/ast.h b/src/semantics/ast.h
--- a/src/semantics/ast.h
+++ b/src/semantics/ast.h
struct AST_Case_Statement
{
enum AST_Type type;
- struct AST_Expression *expression;
+
+ struct AST_Expression *control;
struct AST *statement;
};
struct AST_Default_Statement
enum AST_Type type;
struct AST *statement;
};
+ struct AST_Break_Continue_Statement
+ {
+ enum AST_Type type;
+ struct AST *parent;
+ };
struct AST_Compound_Statement
{
enum AST_Type type;
struct AST_Switch_Statement
{
enum AST_Type type;
- struct AST* condition;
+ struct AST_Expression* condition;
struct AST* body_statement;
+
+ struct Queue *cases;
};
struct AST_Return_Statement
{
struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST *statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope);
+ struct AST_Case_Statement* get_case_statement_tree(struct AST *statement,struct AST_Expression *control,struct AST_Switch_Statement *parent,struct Translation_Data *translation_data);
struct AST_Default_Statement* get_default_statement_tree(struct AST *statement,struct Translation_Data *translation_data);
+ struct AST_Break_Continue_Statement* get_break_continue_statement_tree(struct AST *parent,struct Translation_Data *translation_data,enum AST_Type break_or_continue);
struct AST_Compound_Statement* get_compound_statement_tree(struct Scope *parent_scope);
struct AST_If_Statement* get_if_statement_tree();
- struct AST_Switch_Statement* get_switch_statement_tree();
+ struct AST_Switch_Statement* get_switch_statement_tree(struct AST_Expression *condidion,struct AST *body_statement);
struct AST_While_Statement* get_while_statement_tree();
struct AST_Do_While_Statement* get_do_while_statement_tree();
struct AST_For_Statement* get_for_statement_tree();
+ _Bool ast_is_a_constant_expression(struct AST *ast,struct Translation_Data *translation_data);
+
void delete_ast(struct AST* ast);
void delete_ast_error(struct AST_Error *error);
void delete_ast_declaration_error(struct AST_Declaration_Error *error);
void delete_ast_designator_expression(struct AST_Designator *designator);
void delete_ast_unary_expression(struct AST_Unary_Expression *unary_expression);
void delete_ast_labeled_statement(struct AST_Labeled_Statement *labeled_statement);
+ void delete_ast_default_statement(struct AST_Default_Statement *default_statement);
+ void delete_ast_break_continue_statement(struct AST_Break_Continue_Statement *break_continue);
void delete_ast_compound_statement(struct AST_Compound_Statement *compound_statement);
void delete_ast_for_statement(struct AST_For_Statement *for_statement);
void delete_ast_while_statemtent(struct AST_While_Statement *while_statement);
void delete_ast_if_statemtent(struct AST_If_Statement *if_statement);
void delete_ast_goto_statemtent(struct AST_Goto_Statement *goto_statement);
void delete_ast_switch_statement(struct AST_Switch_Statement *switch_statement);
+ void delete_ast_case_statement(struct AST_Case_Statement *case_statement);
void delete_ast_return_statement(struct AST_Return_Statement *return_statement);
void delete_ast_type_definition(struct AST_Type_Definition *type_definition);
void delete_ast_object_declaration(struct AST_Object_Declaration *object_declaration);
F diff --git a/src/semantics/ast.hh b/src/semantics/ast.hh
--- a/src/semantics/ast.hh
+++ b/src/semantics/ast.hh
struct AST_Designator;
struct AST_Unary_Expression;
struct AST_Labeled_Statement;
+ struct AST_Case_Statement;
+ struct AST_Default_Statement;
+ struct AST_Break_Continue_Statement;
struct AST_Compound_Statement;
struct AST_For_Statement;
struct AST_While_Statement;
F diff --git a/src/semantics/constraints/statement_constraints.c b/src/semantics/constraints/statement_constraints.c
--- a/src/semantics/constraints/statement_constraints.c
+++ b/src/semantics/constraints/statement_constraints.c
#define WONKY_STATEMENT_CONSTRAINTS_C WONKY_STATEMENT_CONSTRAINTS_C
#include <statement_constraints.h>
+ _Bool constraint_check_case_statement(struct AST_Case_Statement *case_statement,struct AST_Switch_Statement *parent,struct Translation_Data *translation_data)
+ {
+ if(parent==NULL)
+ {
+ push_translation_error("case statement used outside of a switch",translation_data);
+ return 0;
+ }
+ assert(case_statement->control!=NULL);
+ if(!ast_is_a_constant_expression((struct AST*)case_statement->control,translation_data))
+ {
+ push_translation_error("control expression in case statement is not a constant expression",translation_data);
+ return 0;
+ }
+ return 1;
+ }
_Bool constraint_check_labeled_statement(struct AST_Labeled_Statement *label,struct Translation_Data *translation_data)
{
return 1;
return 1;
}
+ _Bool constraint_check_break_continue_statement(struct AST_Break_Continue_Statement* break_statement,struct Translation_Data *translation_data)
+ {
+ if(break_statement->parent==NULL)
+ {
+ if(break_statement->type==ST_BREAK)
+ push_translation_error("Using a break statement outside of a loop or switch statement",translation_data);
+ else
+ push_translation_error("Using a continue statement outside of a loop statement",translation_data);
+
+ return 0;
+ }else
+ {
+ return 1;
+ }
+ }
#endif
F diff --git a/src/semantics/constraints/statement_constraints.h b/src/semantics/constraints/statement_constraints.h
--- a/src/semantics/constraints/statement_constraints.h
+++ b/src/semantics/constraints/statement_constraints.h
- /*_Bool constraint_check_case_statement(struct ,struct Translation_Data *translation_data);*/
+ _Bool constraint_check_case_statement(struct AST_Case_Statement *case_statement,struct AST_Switch_Statement *parent,struct Translation_Data *translation_data);
/*_Bool constraint_check_default(struct ,struct Translation_Data *translation_data);*/
_Bool constraint_check_labeled_statement(struct AST_Labeled_Statement *label,struct Translation_Data *translation_data);
_Bool constraint_check_for_statement(struct AST_For_Statement *for_statement,struct Translation_Data *translation_data);
_Bool constraint_check_goto_statement(struct AST_Goto_Statement *goto_statement,struct Translation_Data *translation_data);
- _Bool constraint_check_continue_statement(struct AST_Labeled_Statement *continue_statement,struct Translation_Data *translation_data);
- _Bool constraint_check_break_statement(struct AST* break_statement,struct Translation_Data *translation_data);
+
+ _Bool constraint_check_break_continue_statement(struct AST_Break_Continue_Statement* break_statement,struct Translation_Data *translation_data);
/*must be in a function and must return with the function return type , empty expressions are premmited under functions returning void*/
_Bool constraint_check_return_statement(struct AST *return_expression,struct Type *return_type,struct Translation_Data *translation_data);