diff options
Diffstat (limited to 'src/frontend/parser.c')
-rw-r--r-- | src/frontend/parser.c | 159 |
1 files changed, 119 insertions, 40 deletions
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 |