From 76fc38b3cdfded2911b464baa7b182b5102318d1 Mon Sep 17 00:00:00 2001 From: Galin Simeonov Date: Thu, 3 Jun 2021 12:38:37 +0300 Subject: work on generated C code --- src/frontend/lexer.c | 18 ++++ src/frontend/lexer.h | 7 ++ src/frontend/parser.c | 281 +++++++++++++++++++++++++++++++++++++++++++------- src/frontend/parser.h | 46 ++++++++- 4 files changed, 314 insertions(+), 38 deletions(-) (limited to 'src/frontend') diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c index 6dc348d..de8ff95 100644 --- a/src/frontend/lexer.c +++ b/src/frontend/lexer.c @@ -37,14 +37,26 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d return get_token(src->src+src->where_in_src-sizeof("on")+1,sizeof("on")-1,KW_ON,src->current_row,src->current_column); if(check_and_move_if_on_word("[",sizeof("[")-1,src,0)) return get_token(src->src+src->where_in_src-sizeof("[")+1,sizeof("[")-1,KW_OPEN_SQUARE,src->current_row,src->current_column); + if(check_and_move_if_on_word("(",sizeof("(")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof("(")+1,sizeof("(")-1,KW_OPEN_NORMAL,src->current_row,src->current_column); + if(check_and_move_if_on_word(")",sizeof(")")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof(")")+1,sizeof(")")-1,KW_CLOSE_NORMAL,src->current_row,src->current_column); if(check_and_move_if_on_word(",",sizeof(",")-1,src,0)) return get_token(src->src+src->where_in_src-sizeof(",")+1,sizeof(",")-1,KW_COMMA,src->current_row,src->current_column); + if(check_and_move_if_on_word(".",sizeof(".")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof(".")+1,sizeof(".")-1,KW_DOT,src->current_row,src->current_column); if(check_and_move_if_on_word("]",sizeof("]")-1,src,0)) return get_token(src->src+src->where_in_src-sizeof("]")+1,sizeof("]")-1,KW_CLOSE_SQUARE,src->current_row,src->current_column); if(check_and_move_if_on_word(";",sizeof(";")-1,src,0)) return get_token(src->src+src->where_in_src-sizeof(";")+1,sizeof(";")-1,KW_SEMI_COLUMN,src->current_row,src->current_column); if(check_and_move_if_on_word("|",sizeof("|")-1,src,0)) return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column); + if(check_and_move_if_on_word("||",sizeof("||")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof("||")+1,sizeof("||")-1,KW_OR,src->current_row,src->current_column); + if(check_and_move_if_on_word("&&",sizeof("&&")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof("&&")+1,sizeof("&&")-1,KW_AND,src->current_row,src->current_column); + if(check_and_move_if_on_word("!",sizeof("!")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof("!")+1,sizeof("!")-1,KW_NOT,src->current_row,src->current_column); if(check_and_move_if_on_word("starting",sizeof("starting")-1,src,1)) return get_token(src->src+src->where_in_src-sizeof("starting")+1,sizeof("starting")-1,KW_STARTING,src->current_row,src->current_column); if(check_and_move_if_on_word("states",sizeof("states")-1,src,1)) @@ -157,4 +169,10 @@ void push_token_into_map(struct token *token,struct Map *map,void *thing) { Map_Push(map,token->data,token->size,thing); } +void id_token_to_upper_case(struct token *token) +{ + size_t i; + for(i=0;isize;++i) + token->data[i]=toupper(token->data[i]); +} #endif diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h index d102540..266beea 100644 --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.h @@ -20,6 +20,8 @@ enum Keyword KW_EOF, KW_OPEN_SQUARE, KW_CLOSE_SQUARE, + KW_OPEN_NORMAL, + KW_CLOSE_NORMAL, KW_PIPE, KW_SEMI_COLUMN, KW_STARTING, @@ -29,6 +31,10 @@ enum Keyword KW_EXECUTE, KW_TRANSITIONS, KW_COMMA, + KW_DOT, + KW_AND, + KW_OR, + KW_NOT, }; struct token { @@ -45,6 +51,7 @@ struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size void skip_white_space(struct Source *src); void push_token_into_map(struct token *token,struct Map *map,void *thing); +void id_token_to_upper_case(struct token *token); void delete_token(struct token *token); 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 diff --git a/src/frontend/parser.h b/src/frontend/parser.h index eaede84..74f2ed8 100644 --- a/src/frontend/parser.h +++ b/src/frontend/parser.h @@ -5,6 +5,9 @@ #include #include +#define AS_BIN_EXPR_PTR(x) ((struct AST_Binary_Expression*)x) +#define AS_UN_EXPR_PTR(x) ((struct AST_Unary_Expression*)x) +#define AS_UNCK_EXPR_PTR(x) ((struct AST_Unchecked_State*)x) enum AST_Type { AST_TYPE_TRANSLATION_UNIT, @@ -17,6 +20,11 @@ enum AST_Type AST_TYPE_TRANSITIONS, AST_TYPE_COMMAND, AST_TYPE_PIPELINE, + AST_TYPE_OP_AND, + AST_TYPE_OP_OR, + AST_TYPE_OP_NOT, + AST_TYPE_OP_SELECTOR, + AST_TYPE_UNFINISHED_STATE, }; struct AST { @@ -48,7 +56,7 @@ struct AST_Events struct AST_Transition { enum AST_Type type; - struct AST_State *from; + struct AST *from; struct AST_State *to; struct AST_Event *event; struct AST_Pipeline *pipeline; @@ -75,6 +83,7 @@ struct AST_Machine { enum AST_Type type; struct token *id; + struct AST_State *starting_state; struct AST_States *states; struct AST_Events *events; struct AST_Transitions *transitions; @@ -83,9 +92,26 @@ struct AST_Translation_Unit { enum AST_Type type; struct Map *used_commands_map; + struct Map *machines_map; size_t number_of_machines; struct AST_Machine *machines[]; }; +struct AST_Binary_Expression +{ + enum AST_Type type; + struct AST *left; + struct AST *right; +}; +struct AST_Unary_Expression +{ + enum AST_Type type; + struct AST *operand; +}; +struct AST_Unchecked_State +{ + enum AST_Type type; + struct token *name; +}; struct AST* parse_source(struct Translation_Data *translation_data); @@ -102,18 +128,28 @@ 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); +struct AST* parse_expression(struct Translation_Data *translation_data); +struct AST* parse_or_expression(struct Translation_Data *translation_data); +struct AST* parse_and_expression(struct Translation_Data *translation_data); +struct AST* parse_not_expression(struct Translation_Data *translation_data); +struct AST* parse_primary_expression(struct Translation_Data *translation_data); 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_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_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 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_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data); void delete_ast(struct AST* ast); void delete_ast_event(struct AST_Event* ast); @@ -127,6 +163,10 @@ void delete_ast_machine(struct AST_Machine* ast); void delete_ast_transitions(struct AST_Transitions* ast); 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 pointer_array_fill(void **array,struct Queue *q); struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim); -- cgit v1.2.3