aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGalin Simeonov <gts@volconst.com>2021-06-04 16:42:52 +0300
committerGalin Simeonov <gts@volconst.com>2021-07-15 18:04:59 +0300
commita26684a417729699e95b335a3d00798237ffba9b (patch)
tree6cd73bc90fbe5fd435b8cc721455d0a70420a4ac
parentb845e4754be86d2216733d9bea75cb301f38739d (diff)
downloadMEGATRON-a26684a417729699e95b335a3d00798237ffba9b.tar.gz
added the if statement
-rw-r--r--src/backend/backend.c31
-rw-r--r--src/backend/backend.h1
-rw-r--r--src/backend/targets/C/ast_to_c.c76
-rw-r--r--src/backend/targets/C/ast_to_c.h4
-rw-r--r--src/backend/targets/print/print.c27
-rw-r--r--src/backend/targets/print/print.h1
-rw-r--r--src/frontend/lexer.c8
-rw-r--r--src/frontend/lexer.h2
-rw-r--r--src/frontend/parser.c159
-rw-r--r--src/frontend/parser.h21
-rw-r--r--tests/.test6.swp (renamed from tests/.test5.swp)bin12288 -> 12288 bytes
-rw-r--r--tests/test44
-rw-r--r--tests/test57
-rw-r--r--tests/test626
14 files changed, 306 insertions, 61 deletions
diff --git a/src/backend/backend.c b/src/backend/backend.c
index 512d247..ff9d0bf 100644
--- a/src/backend/backend.c
+++ b/src/backend/backend.c
@@ -20,10 +20,7 @@ struct State_And_Transitions** extract_transition_table(struct AST_States *state
/*traverse transitions and push them into the queue of their coresponding state*/
for(i=0;i<transitions->size;++i)
{
- hold_state=extract_state(transitions->transitions[i]->from,states);
-
- assert(hold_state!=NULL);
-
+ hold_state=transitions->transitions[i]->from;
Queue_Push(qs+hold_state->number,transitions->transitions[i]);
}
@@ -101,7 +98,7 @@ void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *un
size_t i;
for(i=0;i<machine->transitions->size;++i)
{
- machine->transitions->transitions[i]->from=anotate_expression(machine->transitions->transitions[i]->from,unit,machine,translation_data);
+ machine->transitions->transitions[i]->statement=anotate_statement(machine->transitions->transitions[i]->statement,unit,machine,translation_data);
}
if(has_new_errors(translation_data))
{
@@ -109,6 +106,17 @@ void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *un
delete_ast_machine(machine);
}
}
+struct AST* anotate_statement(struct AST *statement,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data)
+{
+ if(statement==NULL)return NULL;
+ if(statement->type==AST_TYPE_IF)
+ {
+ ((struct AST_If_Statement*)statement)->condition=anotate_expression(((struct AST_If_Statement*)statement)->condition,unit,current_machine,translation_data);
+ }else
+ {
+ return statement;
+ }
+}
struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data)
{
struct AST_Machine *hold_machine;
@@ -131,8 +139,17 @@ struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Uni
}else
{
hold_left=(struct AST*)ast_check_state((struct AST_Unchecked_State*)hold_right,hold_machine->states,translation_data);
- ((struct AST_State*)hold_left)->parent=hold_machine;
- return hold_left;
+ if(hold_left)
+ {
+ ((struct AST_State*)hold_left)->parent=hold_machine;
+ delete_ast(hold_right);
+ return hold_left;
+ }else
+ {
+ push_error_with_token("state id from foreign machine is undefined",((struct AST_Unchecked_State*)hold_right)->name,translation_data);
+ delete_ast(hold_right);
+ return NULL;
+ }
}
}else
{
diff --git a/src/backend/backend.h b/src/backend/backend.h
index 8b865fd..d292776 100644
--- a/src/backend/backend.h
+++ b/src/backend/backend.h
@@ -21,6 +21,7 @@ struct AST_State* extract_state(struct AST *expression,struct AST_States *states
void anotate_unchecked_states(struct AST_Translation_Unit *unit,struct Translation_Data *translation_data);
void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *unit,struct Translation_Data *translation_data);
+struct AST* anotate_statement(struct AST *statement,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data);
struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data);
_Bool expression_is_binary(struct AST* expression);
diff --git a/src/backend/targets/C/ast_to_c.c b/src/backend/targets/C/ast_to_c.c
index 3ce923d..9c8b38d 100644
--- a/src/backend/targets/C/ast_to_c.c
+++ b/src/backend/targets/C/ast_to_c.c
@@ -189,7 +189,8 @@ void ast_transitions_of_state_to_c(FILE *out,struct AST_Machine *machine,struct
ast_event_to_c_enum(out,machine,vector->transitions[i]->event);
fprintf(out,":\n");
- ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline);
+ //ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline);
+ ast_statement_to_c(out,3,vector->transitions[i]->statement);
fprintf(out,"\t\t\tmachine_states[");
ast_token_to_c(out,machine->id);
fprintf(out,"]=");
@@ -370,4 +371,77 @@ void ast_to_c_print_comment(FILE *out,char *comment)
fprintf(out,"%s\n",comment);
fprintf(out,"*/\n");
}
+void ast_statement_to_c(FILE *out,size_t indentation,struct AST *statement)
+{
+ if(statement==NULL)return;
+ if(statement->type==AST_TYPE_PIPELINE)
+ ast_pipeline_to_c(out,indentation,(struct AST_Pipeline*)statement);
+ else if(statement->type==AST_TYPE_IF)
+ ast_if_to_c(out,indentation,(struct AST_If_Statement*)statement);
+ else
+ assert(0);
+
+}
+void ast_if_to_c(FILE *out,size_t indentation,struct AST_If_Statement *statement)
+{
+ ast_to_c_print_tabs(out,indentation);
+ fprintf(out,"if");
+ ast_expression_to_c(out,statement->condition);
+ fprintf(out,"\n");
+
+ ast_to_c_print_tabs(out,indentation);
+ fprintf(out,"{\n");
+
+ ast_statement_to_c(out,indentation+1,statement->body);
+
+ ast_to_c_print_tabs(out,indentation);
+ fprintf(out,"}");
+ if(statement->else_statement)
+ {
+ fprintf(out,"else{\n");
+
+ ast_statement_to_c(out,indentation+1,statement->else_statement);
+
+ ast_to_c_print_tabs(out,indentation);
+ fprintf(out,"}");
+ }
+ fprintf(out,"\n");
+}
+void ast_expression_to_c(FILE *out,struct AST *expression)
+{
+ fprintf(out,"(");
+ switch(expression->type)
+ {
+ case AST_TYPE_OP_OR:
+ ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->left);
+ fprintf(out,"||");
+ ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->right);
+ break;
+ case AST_TYPE_OP_NOT:
+ fprintf(out,"!");
+ ast_expression_to_c(out,AS_UN_EXPR_PTR(expression)->operand);
+ break;
+ case AST_TYPE_OP_AND:
+ ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->left);
+ fprintf(out,"&&");
+ ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->right);
+ break;
+ case AST_TYPE_STATE:
+ ast_expression_state_to_c(out,(struct AST_State*)expression);
+ break;
+ case AST_TYPE_OP_SELECTOR:
+ assert(!"selector in final product!\n");
+ default:
+ assert(0);
+ }
+ fprintf(out,")");
+}
+void ast_expression_state_to_c(FILE *out,struct AST_State *state)
+{
+ fprintf(out,"machine_states[");
+ ast_token_to_c(out,state->parent->id);
+ fprintf(out,"]==");
+ ast_state_to_c_function_name(out,state->parent,state);
+
+}
#endif
diff --git a/src/backend/targets/C/ast_to_c.h b/src/backend/targets/C/ast_to_c.h
index fb3e729..299d6db 100644
--- a/src/backend/targets/C/ast_to_c.h
+++ b/src/backend/targets/C/ast_to_c.h
@@ -44,6 +44,10 @@ void ast_machines_to_c_array(FILE *out,struct AST_Translation_Unit *translation_
void ast_machines_to_c_enum(FILE *out,struct AST_Translation_Unit *translation_unit);
void ast_event_to_c_enum(FILE *out,struct AST_Machine *machine,struct AST_Event *event);
+void ast_statement_to_c(FILE *out,size_t indentation,struct AST *statement);
+void ast_if_to_c(FILE *out,size_t indentation,struct AST_If_Statement *statement);
+void ast_expression_to_c(FILE *out,struct AST *expression);
+void ast_expression_state_to_c(FILE *out,struct AST_State *state);
void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit);
void ast_to_c_print_internal_stuff_for_body(FILE *out);
diff --git a/src/backend/targets/print/print.c b/src/backend/targets/print/print.c
index 7649b91..3c33438 100644
--- a/src/backend/targets/print/print.c
+++ b/src/backend/targets/print/print.c
@@ -81,6 +81,12 @@ void print_keyword_enum(enum Keyword code)
case KW_NOT:
printf("KW_NOT");
break;
+ case KW_IF:
+ printf("KW_IF");
+ break;
+ case KW_ELSE:
+ printf("KW_ELSE");
+ break;
default:
printf("LEXERROR");
}
@@ -158,6 +164,9 @@ void print_ast_enum(enum AST_Type type)
case AST_TYPE_UNFINISHED_STATE:
printf("AST_TYPE_UNFINISHED_STATE");
break;
+ case AST_TYPE_IF:
+ printf("AST_TYPE_IF");
+ break;
default:
printf("AST_NOP");
}
@@ -210,6 +219,9 @@ void print_ast(struct AST *tree)
case AST_TYPE_UNFINISHED_STATE:
print_ast_unchecked_state((struct AST_Unchecked_State*)tree);
break;
+ case AST_TYPE_IF:
+ print_ast_if_statement((struct AST_If_Statement*)tree);
+ break;
default:
printf("noast");
}
@@ -262,16 +274,16 @@ void print_ast_transition(struct AST_Transition* tree)
assert(tree);
printf("TRANSITION [\nFROM");
- print_ast(tree->from);
+ print_ast_state(tree->from);
printf(" TO ");
print_ast_state(tree->to);
printf(" COMMAND {");
- if(tree->pipeline==NULL)
+ if(tree->statement==NULL)
{
printf("NULL");
}else
{
- print_ast_pipeline(tree->pipeline);
+ print_ast(tree->statement);
}
}
@@ -381,4 +393,13 @@ void print_ast_unchecked_state(struct AST_Unchecked_State *tree)
{
print_token(tree->name);
}
+void print_ast_if_statement(struct AST_If_Statement *tree)
+{
+ printf("if <");
+ print_ast(tree->condition);
+ printf(">\n");
+ print_ast(tree->body);
+ if(tree->else_statement)
+ print_ast(tree->else_statement);
+}
#endif
diff --git a/src/backend/targets/print/print.h b/src/backend/targets/print/print.h
index d318792..b21a00c 100644
--- a/src/backend/targets/print/print.h
+++ b/src/backend/targets/print/print.h
@@ -25,6 +25,7 @@ void print_ast_translation_unit(struct AST_Translation_Unit *tree);
void print_ast_binary_expression(struct AST_Binary_Expression *tree);
void print_ast_unary_expression(struct AST_Unary_Expression *tree);
void print_ast_unchecked_state(struct AST_Unchecked_State *tree);
+void print_ast_if_statement(struct AST_If_Statement *tree);
void print_error(struct Error *error);
void print_errors(struct Translation_Data *translation_data);
diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c
index 668d7cd..a832a17 100644
--- a/src/frontend/lexer.c
+++ b/src/frontend/lexer.c
@@ -8,7 +8,7 @@
#define LEX_ERROR(x) {push_lexing_error(x,src,translation_data); return get_token(src->src+src->where_in_src,0,KW_NOP,src->current_row,src->current_column);}
/*
- * placeholder very slow lexer that I will probabbly not replace
+ * placeholder very slow ( and very very bad ) lexer that I will probabbly not replace
*/
void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data)
{
@@ -69,9 +69,11 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
return get_token(src->src+src->where_in_src-sizeof("event")+1,sizeof("event")-1,KW_EVENT,src->current_row,src->current_column);
if(check_and_move_if_on_word("transitions",sizeof("transitions")-1,src,1))
return get_token(src->src+src->where_in_src-sizeof("transitions")+1,sizeof("transitions")-1,KW_TRANSITIONS,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("if",sizeof("if")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("if")+1,sizeof("if")-1,KW_IF,src->current_row,src->current_column);
-
-
+ if(check_and_move_if_on_word("else",sizeof("else")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("else")+1,sizeof("else")-1,KW_ELSE,src->current_row,src->current_column);
diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h
index 266beea..54c88fa 100644
--- a/src/frontend/lexer.h
+++ b/src/frontend/lexer.h
@@ -35,6 +35,8 @@ enum Keyword
KW_AND,
KW_OR,
KW_NOT,
+ KW_IF,
+ KW_ELSE,
};
struct token
{
diff --git a/src/frontend/parser.c b/src/frontend/parser.c
index fa692f5..7af7af2 100644
--- a/src/frontend/parser.c
+++ b/src/frontend/parser.c
@@ -30,9 +30,9 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
{
hold_machine=parse_machine(translation_data);
/*TODO check for repeated machine ids*/
- Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
if(hold_machine)
{
+ Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
Queue_Push(machines,hold_machine);
}
else
@@ -307,8 +307,6 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
while((hold_transition=parse_transition(translation_data,states,events))!=NULL)
{
Queue_Push(transitions,hold_transition);
- if(!get_and_check(translation_data,KW_SEMI_COLUMN))
- break;
}
if(transitions->size==0)
@@ -331,49 +329,106 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
{
struct AST_Transition *ret;
- struct AST *hold_from;
+ struct AST_State *hold_from;
struct AST_State *hold_to;
struct AST_Event *hold_event;
- struct AST_Pipeline *hold_pipeline=NULL;
+ struct AST *hold_statement=NULL;
struct token *hold_token;
if(get_and_check(translation_data,KW_FROM))
{
- hold_from=parse_expression(translation_data);
- if(hold_from!=NULL)
+ if(get_kw(translation_data)==KW_ID)
{
- if(get_and_check(translation_data,KW_TO))
+ 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_kw(translation_data)==KW_ID)
+ if(get_and_check(translation_data,KW_TO))
{
- 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_kw(translation_data)==KW_ID)
{
- if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ 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_kw(translation_data)==KW_ID)
+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
{
- 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)
+ if(get_kw(translation_data)==KW_ID)
{
- if(get_and_check(translation_data,KW_EXECUTE))
- if((hold_pipeline=parse_pipeline(translation_data))==NULL)
- { push_parsing_error("after execute",translation_data); return NULL; }
- /*GOAL*/
- return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
- }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; }
+ 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)
+ {
+
+ if(!get_and_check(translation_data,KW_SEMI_COLUMN) && (hold_statement=parse_statement(translation_data,states,events))==NULL)
+ { push_parsing_error("in statement of transition",translation_data); return NULL; }
+
+ /*GOAL!!!!!*/
+ return get_ast_transition(hold_from,hold_to,hold_event,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; }
}
+
+/*
+ * statement : 'execute' pipeline ; | 'if' expression statement [ else statement ]
+ */
+struct AST* parse_statement(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+{
+ 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);
+ delete_ast(hold_body);
+ return NULL;
+ }
+ }else if(get_and_check(translation_data,KW_IF))
+ {
+ hold_expression=parse_expression(translation_data);
+ hold_body=parse_statement(translation_data,states,events);
+ if(hold_body)
+ {
+ if(get_and_check(translation_data,KW_ELSE))
+ {
+ hold_else=parse_statement(translation_data,states,events);
+ if(hold_else==NULL)
+ {
+ push_parsing_error("expected a statement after else",translation_data);
+ delete_ast(hold_expression);
+ delete_ast(hold_body);
+ 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);
+ if(hold_expression)
+ delete_ast(hold_expression);
+ return NULL;
+ }
+ }else
+ {
+ return NULL;
+ }
+}
/*
* pipeline: [ command ( | command )* ]
*
@@ -523,7 +578,7 @@ struct AST_Events* get_ast_events(struct Queue *events)
return ret;
}
-struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline)
+struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *statement)
{
struct AST_Transition *ret;
ret=malloc(sizeof(struct AST_Transition));
@@ -531,7 +586,7 @@ struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,
ret->from=from;
ret->to=to;
ret->event=event;
- ret->pipeline=pipeline;
+ ret->statement=statement;
return ret;
}
@@ -632,7 +687,9 @@ void delete_ast(struct AST* ast)
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)
@@ -660,8 +717,8 @@ void delete_ast_events(struct AST_Events* ast)
void delete_ast_transition(struct AST_Transition* ast)
{
if(ast==NULL)return;
- if(ast->pipeline!=NULL)
- delete_ast_pipeline(ast->pipeline);
+ if(ast->statement!=NULL)
+ delete_ast(ast->statement);
free(ast);
}
void delete_ast_command(struct AST_Command* ast)
@@ -842,7 +899,7 @@ struct AST* parse_not_expression(struct Translation_Data *translation_data)
return parse_primary_expression(translation_data);
}
/*
- * primary-expression: (expression) | id | id.id
+ * primary-expression: (expression) | id.id
*/
struct AST* parse_primary_expression(struct Translation_Data *translation_data)
{
@@ -880,7 +937,9 @@ struct AST* parse_primary_expression(struct Translation_Data *translation_data)
}
}else
{
- return (struct AST*)hold_id1;
+ delete_ast((struct AST*)hold_id1);
+ push_parsing_error("expected a selector",translation_data);
+ return NULL;
}
}else
{
@@ -921,18 +980,31 @@ struct AST_Unchecked_State* get_ast_unchecked_state(struct token *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);
- delete_ast_unchecked_state(state);
if(ret==NULL)
{
- push_parsing_error("undefined state",translation_data);
+ 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;
}
}
@@ -956,4 +1028,11 @@ 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
diff --git a/src/frontend/parser.h b/src/frontend/parser.h
index a9f6b89..4745f63 100644
--- a/src/frontend/parser.h
+++ b/src/frontend/parser.h
@@ -25,6 +25,7 @@ enum AST_Type
AST_TYPE_OP_NOT,
AST_TYPE_OP_SELECTOR,
AST_TYPE_UNFINISHED_STATE,
+ AST_TYPE_IF,
};
struct AST
{
@@ -58,10 +59,10 @@ struct AST_Events
struct AST_Transition
{
enum AST_Type type;
- struct AST *from;
+ struct AST_State *from;
struct AST_State *to;
struct AST_Event *event;
- struct AST_Pipeline *pipeline;
+ struct AST *statement;
};
struct AST_Command
{
@@ -114,6 +115,13 @@ struct AST_Unchecked_State
enum AST_Type type;
struct token *name;
};
+struct AST_If_Statement
+{
+ enum AST_Type type;
+ struct AST *condition;
+ struct AST *body;
+ struct AST *else_statement;
+};
struct AST* parse_source(struct Translation_Data *translation_data);
@@ -126,6 +134,9 @@ struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)
struct AST_Event* parse_event(struct Translation_Data *translation_data);
struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events );
struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);
+
+struct AST* parse_statement(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);
+
struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data);
struct AST_Command* parse_command(struct Translation_Data *translation_data);
struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states);
@@ -140,16 +151,17 @@ struct AST_State* get_ast_state(struct token *id);
struct AST_Event* get_ast_event(struct token *id);
struct AST_States* get_ast_states(struct Queue *states);
struct AST_Events* get_ast_events(struct Queue *events);
-struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
+struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *statement);
struct AST_Command* get_ast_command(struct token *function_name,struct token *argument);
struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline);
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_Transitions* get_ast_transitions(struct Queue *transitions);
struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map);
-
struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type);
struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type);
struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name);
+struct AST_If_Statement* get_ast_if_statement(struct AST *condition,struct AST *body,struct AST *else_statement);
+
struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data);
@@ -168,6 +180,7 @@ void delete_ast_translation_unit(struct AST_Translation_Unit *ast);
void delete_ast_binary_expression(struct AST_Binary_Expression *ast);
void delete_ast_unary_expression(struct AST_Unary_Expression *ast);
void delete_ast_unchecked_state(struct AST_Unchecked_State *ast);
+void delete_ast_if_statement(struct AST_If_Statement *ast);
void pointer_array_fill(void **array,struct Queue *q);
diff --git a/tests/.test5.swp b/tests/.test6.swp
index 6e03612..dc85c11 100644
--- a/tests/.test5.swp
+++ b/tests/.test6.swp
Binary files differ
diff --git a/tests/test4 b/tests/test4
index 579e54d..4610e2c 100644
--- a/tests/test4
+++ b/tests/test4
@@ -19,6 +19,8 @@ machine temp_switch
starting on A;
transitions
[
- from ( !A && !light_on ) to B on event A execute kek;
+ from A to B on event A
+ if !light_bulb.light_on
+ execute kek;
];
];
diff --git a/tests/test5 b/tests/test5
index fc9ff67..fb72d41 100644
--- a/tests/test5
+++ b/tests/test5
@@ -5,7 +5,10 @@ machine A
starting on A;
transitions
[
- from A to A on event A given (B.C && !C.D)
- execute eke;
+ from A to A on event A
+ if (A.A && !A.A)
+ execute eke;
+ else
+ execute asdf;
];
];
diff --git a/tests/test6 b/tests/test6
new file mode 100644
index 0000000..3fed6d3
--- /dev/null
+++ b/tests/test6
@@ -0,0 +1,26 @@
+machine light_bulb
+[
+ states [ light_on , light_off ];
+ events [ turn_on , turn_off , switch ];
+ starting on light_off;
+ transitions
+ [
+ from light_on to light_off on event turn_off execute kek2 | kek;
+ from light_on to light_off on event switch;
+ from light_off to light_on on event turn_on;
+ from light_off to light_on on event switch execute kek;
+
+ ];
+];
+machine temp_switch
+[
+ states [A,B];
+ events [A];
+ starting on A;
+ transitions
+ [
+ from A to B on event A granted !light_bulb.light_on
+ if !light_bulb.light_on
+ execute kek;
+ ];
+];