diff options
Diffstat (limited to 'src/frontend/parser.c')
-rw-r--r-- | src/frontend/parser.c | 281 |
1 files changed, 246 insertions, 35 deletions
diff --git a/src/frontend/parser.c b/src/frontend/parser.c index 45752e7..a260622 100644 --- a/src/frontend/parser.c +++ b/src/frontend/parser.c @@ -13,17 +13,25 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra { struct Queue *machines; struct Map *hold_command_map; + struct Map *hold_machines_map; struct AST_Machine *hold_machine; machines=calloc(1,sizeof(struct Queue)); + hold_command_map=malloc(sizeof(struct Map)); Map_Init(hold_command_map); + hold_machines_map=malloc(sizeof(struct Map)); + Map_Init(hold_machines_map); + translation_data->hold_command_map=hold_command_map; + translation_data->hold_machines_map=hold_machines_map; while(!get_and_check(translation_data,KW_EOF)) { 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) { Queue_Push(machines,hold_machine); @@ -37,7 +45,7 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra return NULL; } } - return get_ast_translation_unit(machines,hold_command_map); + return get_ast_translation_unit(machines,hold_command_map,hold_machines_map); } /* * machine: 'machine' id '[' machine-inner ']' ';' @@ -308,6 +316,10 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla { push_parsing_error("there are no transitions",translation_data); return NULL; + }else if(has_new_errors(translation_data)) + { + push_parsing_error("in transition",translation_data); + return NULL; }else { return get_ast_transitions(transitions); @@ -328,44 +340,39 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat if(get_and_check(translation_data,KW_FROM)) { - if(get_kw(translation_data)==KW_ID) + hold_from=parse_expression(translation_data); + if(hold_from!=NULL) { - hold_token=Queue_Pop(translation_data->tokens); - hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size); - delete_token(hold_token); - if(hold_from!=NULL) + if(get_and_check(translation_data,KW_TO)) { - if(get_and_check(translation_data,KW_TO)) + if(get_kw(translation_data)==KW_ID) { - if(get_kw(translation_data)==KW_ID) + 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) { - 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_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) ) { - if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) ) + if(get_kw(translation_data)==KW_ID) { - if(get_kw(translation_data)==KW_ID) + 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) { - 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_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; } - }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; } + 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; } }else { return NULL; } } /* @@ -402,7 +409,8 @@ struct AST_Command* parse_command(struct Translation_Data *translation_data) if(get_kw(translation_data)==KW_STRING) string=Queue_Pop(translation_data->tokens); ret=get_ast_command(id,string); - Map_Push(translation_data->hold_command_map,ret->argument->data,ret->argument->size,ret); + if(!Map_Check(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size)) + Map_Push(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size,ret); return ret; }else @@ -441,6 +449,7 @@ struct AST_State* get_ast_state(struct token *id) ret=malloc(sizeof(struct AST_State)); ret->name=id; + /*number is assigned in get_ast_states*/ return ret; @@ -473,7 +482,9 @@ struct AST_States* get_ast_states(struct Queue *states) while(states->size>0) { hold_state=Queue_Pop(states); + /*TODO check for redeclaration*/ Map_Push(ret->states_map,hold_state->name->data,hold_state->name->size,hold_state); + ret->states[states->size]=hold_state; hold_state->number=states->size; } @@ -501,6 +512,7 @@ struct AST_Events* get_ast_events(struct Queue *events) while(events->size>0) { hold_event=Queue_Pop(events); + /*TODO check for redeclaration*/ Map_Push(ret->events_map,hold_event->name->data,hold_event->name->size,hold_event); ret->events[events->size]=hold_event; } @@ -510,7 +522,7 @@ struct AST_Events* get_ast_events(struct Queue *events) return ret; } -struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline) +struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline); { struct AST_Transition *ret; ret=malloc(sizeof(struct AST_Transition)); @@ -556,6 +568,7 @@ struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,s ret->states=states; ret->events=events; ret->transitions=transitions; + ret->starting_state=starting_state; return ret; } @@ -713,7 +726,7 @@ void delete_ast_translation_unit(struct AST_Translation_Unit *ast) free(ast->used_commands_map); free(ast); } -struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map) +struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map) { struct AST_Translation_Unit *ret; struct AST_Machine *hold_machine; @@ -721,6 +734,7 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str ret=malloc(sizeof(struct AST_Translation_Unit)+sizeof(struct AST_Machine *[machines->size])); ret->type=AST_TYPE_TRANSLATION_UNIT; ret->used_commands_map=command_map; + ret->machines_map=machines_map; ret->number_of_machines=machines->size; while(machines->size>0) @@ -731,4 +745,201 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str return ret; } +/* + * expression: or-expression + */ +struct AST* parse_expression(struct Translation_Data *translation_data) +{ + return parse_or_expression(translation_data); +} +/* + * or-expression: and-expression [ || and-expression ] + */ +struct AST* parse_or_expression(struct Translation_Data *translation_data) +{ + struct AST *hold_left_expression; + struct AST *hold_right_expression; + + hold_left_expression=parse_and_expression(translation_data); + if(hold_left_expression==NULL) + return NULL; + + if(get_and_check(translation_data,KW_OR)) + { + hold_right_expression=parse_and_expression(translation_data); + if(hold_right_expression==NULL) + { + push_parsing_error("expected expression in right side of ||",translation_data); + delete_ast(hold_left_expression); + return NULL; + } + return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_OR); + }else + { + return hold_left_expression; + } + +} +/* + * and-expression: not-expression [ && not-expression ] + */ +struct AST* parse_and_expression(struct Translation_Data *translation_data) +{ + struct AST *hold_left_expression; + struct AST *hold_right_expression; + + hold_left_expression=parse_not_expression(translation_data); + if(hold_left_expression==NULL) + return NULL; + + if(get_and_check(translation_data,KW_AND)) + { + hold_right_expression=parse_not_expression(translation_data); + if(hold_right_expression==NULL) + { + push_parsing_error("expected expression in right side of &&",translation_data); + delete_ast(hold_left_expression); + return NULL; + } + return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_AND); + }else + { + return hold_left_expression; + } +} +/* + * not-expression: [!]primary-expression + */ +struct AST* parse_not_expression(struct Translation_Data *translation_data) +{ + struct AST *hold_expression; + if(get_and_check(translation_data,KW_NOT)) + { + hold_expression=parse_primary_expression(translation_data); + if(hold_expression!=NULL) + { + return get_ast_unary_expression(hold_expression,AST_TYPE_OP_NOT); + }else + { + push_parsing_error("in '!' expression",translation_data); + return NULL; + } + } + return parse_primary_expression(translation_data); +} +/* + * primary-expression: (expression) | id | id.id + */ +struct AST* parse_primary_expression(struct Translation_Data *translation_data) +{ + struct AST *hold_expression; + struct AST_Unchecked_State *hold_id1; + struct AST_Unchecked_State *hold_id2; + + if(get_and_check(translation_data,KW_OPEN_NORMAL)) + { + hold_expression=parse_expression(translation_data); + if(get_and_check(translation_data,KW_CLOSE_NORMAL)) + { + return hold_expression; + }else + { + push_parsing_error("expected ')' in expression",translation_data); + delete_ast(hold_expression); + return NULL; + } + + }else if(get_kw(translation_data)==KW_ID) + { + hold_id1=get_ast_unchecked_state(Queue_Pop(translation_data->tokens)); + if(get_and_check(translation_data,KW_DOT)) + { + if(get_kw(translation_data)==KW_ID) + { + hold_id2=get_ast_unchecked_state(Queue_Pop(translation_data->tokens)); + return get_ast_binary_expression(hold_id1,hold_id2,AST_TYPE_OP_SELECTOR); + }else + { + push_parsing_error("expected a state id in selector",translation_data); + delete_ast(hold_id1); + return NULL; + } + }else + { + return hold_id1; + } + }else + { + push_parsing_error("expected an expression",translation_data); + return NULL; + } +} +struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type) +{ + struct AST_Binary_Expression *ret; + + ret=malloc(sizeof(struct AST_Binary_Expression)); + ret->type=type; + ret->left=left; + ret->right=right; + + return ret; +} +struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type) +{ + + struct AST_Unary_Expression *ret; + + ret=malloc(sizeof(struct AST_Unary_Expression)); + + ret->type=type; + ret->operand=operand; + + return ret; +} +struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name) +{ + struct AST_Unchecked_State *ret; + + ret=malloc(sizeof(struct AST_Unchecked_State)); + ret->type=AST_TYPE_UNFINISHED_STATE; + ret->name=name; + + 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); + return NULL; + }else + { + return ret; + } +} + +void delete_ast_binary_expression(struct AST_Binary_Expression *ast) +{ + if(ast->right) + delete_ast(ast->right); + if(ast->left) + delete_ast(ast->left); + free(ast); +} +void delete_ast_unary_expression(struct AST_Unary_Expression *ast) +{ + if(ast->operand) + delete_ast(ast->operand); + free(ast); +} +void delete_ast_unchecked_state(struct AST_Unchecked_State *ast) +{ + delete_token(ast->name); + free(ast); +} #endif |