diff options
author | Galin Simeonov <gts@volconst.com> | 2021-05-31 22:02:10 +0300 |
---|---|---|
committer | Galin Simeonov <gts@volconst.com> | 2021-07-15 18:00:15 +0300 |
commit | 255a49ba5a41b3854dbdfebdec75fb6229450507 (patch) | |
tree | 616ea5786cb91d03ef609d32b402941dc30e926b /parser.c | |
parent | f768d9bdb84e846d89aac66a4f3433a44241c298 (diff) | |
download | MEGATRON-255a49ba5a41b3854dbdfebdec75fb6229450507.tar.gz |
added cmake file
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 669 |
1 files changed, 0 insertions, 669 deletions
diff --git a/parser.c b/parser.c deleted file mode 100644 index 3e4e449..0000000 --- a/parser.c +++ /dev/null @@ -1,669 +0,0 @@ -#ifndef PARSER_C -#define PARSER_C PARSER_C -#include <parser.h> - -/* - * parse-unit: machine - * - */ -struct AST* parse_unit(struct Translation_Data *translation_data) -{ - return (struct AST*)parse_machine(translation_data); -} -/* - * machine: 'machine' id '[' machine-inner ']' ';' - * - */ -struct AST_Machine* parse_machine(struct Translation_Data *translation_data) -{ - struct AST_Machine *ret; - struct token *hold_id; - if(get_and_check(translation_data,KW_MACHINE)) - { - if(get_kw(translation_data)==KW_ID) - { - hold_id=Queue_Pop(translation_data->tokens); - if(get_and_check(translation_data,KW_OPEN_SQUARE)) - { - ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data); - if(has_new_errors(translation_data)) - { - delete_ast_machine(ret); - touch_errors(translation_data); - - return NULL; - } - if(get_and_check(translation_data,KW_CLOSE_SQUARE)) - { - if(get_and_check(translation_data,KW_SEMI_COLUMN)) - return ret; - else - { - push_parsing_error("';' expected after machine definition",translation_data); - delete_ast_machine(ret); - return NULL; - } - }else - { - push_parsing_error("closing ']' expected",translation_data); - delete_ast_machine(ret); - return NULL; - } - }else - { - push_parsing_error("opening '[' expected",translation_data); - return NULL; - } - }else - { - push_parsing_error("expected a name for the machine",translation_data); - return NULL; - } - }else - { - push_parsing_error("'machine' expected",translation_data); - return NULL; - } -} -/* - * machine-inner : 'states' '[' states-inner ']' ';' - * 'events' '[' events-inner ']' ';' - * 'transitions' '[' transitions-inner ']' ';' - * 'starting' start-on-inner ';' - */ -struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data) -{ - struct AST_States *states=NULL; - struct AST_Events *events=NULL; - struct AST_Transitions *transitions=NULL; - struct AST_State *starting_state=NULL; - unsigned char i; - for(i=0;i<4;++i) - switch(get_kw(translation_data)) - { - case KW_STATES: - if(states) - { - push_parsing_error("defining two sets of states",translation_data); - goto error_cleanup; - }else - { - chomp(translation_data); - if(get_and_check(translation_data,KW_OPEN_SQUARE)) - { - states=parse_states_inner(translation_data); - if(!get_and_check(translation_data,KW_CLOSE_SQUARE) - || !get_and_check(translation_data,KW_SEMI_COLUMN)) - { - push_parsing_error("expected ']' and ';' at " - "end of states definition",translation_data); - goto error_cleanup; - } - - }else - { - push_parsing_error("expected '[' ",translation_data); - goto error_cleanup; - } - } - break; - case KW_TRANSITIONS: - if(states==NULL && events==NULL) - { - push_parsing_error("defining transitions before states and events",translation_data); - goto error_cleanup; - }else if(transitions) - { - push_parsing_error("defining two sets of transitions",translation_data); - goto error_cleanup; - }else - { - chomp(translation_data); - if(get_and_check(translation_data,KW_OPEN_SQUARE)) - { - transitions=parse_transitions_inner(translation_data,states,events); - if(!get_and_check(translation_data,KW_CLOSE_SQUARE) - || !get_and_check(translation_data,KW_SEMI_COLUMN)) - { - push_parsing_error("expected ']' and ';' at " - "end of transitions definition",translation_data); - goto error_cleanup; - } - }else - { - push_parsing_error("expected '[' ",translation_data); - goto error_cleanup; - } - } - break; - case KW_EVENTS: - if(events) - { - push_parsing_error("defining two sets of transitions",translation_data); - goto error_cleanup; - }else - { - chomp(translation_data); - if(get_and_check(translation_data,KW_OPEN_SQUARE)) - { - events=parse_events_inner(translation_data); - if(!get_and_check(translation_data,KW_CLOSE_SQUARE) - || !get_and_check(translation_data,KW_SEMI_COLUMN)) - { - push_parsing_error("expected ']' and ';' at " - "end of events definition",translation_data); - goto error_cleanup; - } - }else - { - push_parsing_error("expected '[' ",translation_data); - goto error_cleanup; - } - } - break; - case KW_STARTING: - chomp(translation_data); - if(!starting_state) - { - if(states) - { - starting_state=parse_start_on(translation_data,states); - if(!get_and_check(translation_data,KW_SEMI_COLUMN)) - { - push_parsing_error("expected ';' at end " - "of starting state declaration",translation_data); - goto error_cleanup; - } - }else - { - push_parsing_error("states need to be defined" - " before defining a starting one",translation_data); - goto error_cleanup; - } - }else - { - push_parsing_error("starting state is defined",translation_data); - goto error_cleanup; - } - break; - default: - push_parsing_error("expected states transitions or events",translation_data); - goto error_cleanup; - - } - - return get_ast_machine(machine_id,states,events,transitions,starting_state); - -error_cleanup: - push_parsing_error("in machine",translation_data); - if(states)delete_ast_states(states); - if(events)delete_ast_events(events); - if(transitions)delete_ast_transitions(transitions); - return NULL; -} -/* - * states-inner: state (, state)* - * - */ -struct AST_States* parse_states_inner(struct Translation_Data *translation_data) -{ - struct Queue *ids; - struct AST_State *hold_state; - - ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA); - if(ids->size==0) - { - push_parsing_error("there needs to be atleast one state",translation_data); - free(ids); - return NULL; - }else - { - - return get_ast_states(ids); - } -} -/* - * state : id - * - */ -struct AST_State* parse_state(struct Translation_Data *translation_data) -{ - if(get_kw(translation_data)==KW_ID) - return get_ast_state(Queue_Pop(translation_data->tokens)); - else - return NULL; -} -/* - * events-inner: id (, id)* - * - */ -struct AST_Events* parse_events_inner(struct Translation_Data *translation_data) -{ - struct Queue *ids; - ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA); - if(ids->size==0) - { - push_parsing_error("there needs to be atleast one event",translation_data); - return NULL; - }else - { - return get_ast_events(ids); - } -} -struct AST_Event* parse_event(struct Translation_Data *translation_data) -{ - if(get_kw(translation_data)==KW_ID) - return get_ast_event(Queue_Pop(translation_data->tokens)); - else - return NULL; -} -/* - * transitions-inner: ( transition ;)* - */ -struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events) -{ - struct Queue *transitions; - struct AST_Transition *hold_transition; - - transitions=malloc(sizeof(struct Queue)); - Queue_Init(transitions); - - 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) - { - push_parsing_error("there are no transitions",translation_data); - return NULL; - }else - { - return get_ast_transitions(transitions); - } -} -/* - * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ] - * - */ -struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events) -{ - struct AST_Transition *ret; - struct AST_State *hold_from; - struct AST_State *hold_to; - struct AST_Event *hold_event; - struct AST_Pipeline *hold_pipeline=NULL; - struct token *hold_token; - - if(get_and_check(translation_data,KW_FROM)) - { - if(get_kw(translation_data)==KW_ID) - { - 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_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) - { - if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) ) - { - 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) - { - 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; } - }else { return NULL; } -} -/* - * pipeline: [ command ( | command )* ] - * - */ -struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data) -{ - struct Queue *pipeline; - pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE); - if(pipeline->size==0) - { - free(pipeline); - push_parsing_error("pipeline is empty",translation_data); - return NULL; - }else - { - return get_ast_pipeline(pipeline); - } -} -/* - * command: id [ string ] - * - */ -struct AST_Command* parse_command(struct Translation_Data *translation_data) -{ - struct token *id; - struct token *string=NULL; - if(get_kw(translation_data)==KW_ID) - { - id=Queue_Pop(translation_data->tokens); - if(get_kw(translation_data)==KW_STRING) - string=Queue_Pop(translation_data->tokens); - return get_ast_command(id,string); - }else - { - push_parsing_error("expected command id",translation_data); - return NULL; - } -} -/* - * starting-on-inner: 'on' id ; - */ -struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states) -{ - struct token *hold_id; - struct AST_State *hold_state; - - if(get_and_check(translation_data,KW_ON)) - { - if(get_kw(translation_data)==KW_ID) - { - hold_id=Queue_Pop(translation_data->tokens); - hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size); - free(hold_id); - if(hold_state) - { - - return hold_state; - - }else { push_parsing_error("starting state is not defined",translation_data); return NULL; } - }else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; } - }else { push_parsing_error("expected 'on'",translation_data); return NULL; } -} -struct AST_State* get_ast_state(struct token *id) -{ - struct AST_State *ret; - - ret=malloc(sizeof(struct AST_State)); - ret->type=AST_TYPE_STATE; - ret->id=id; - - return ret; -} -struct AST_Event* get_ast_event(struct token *id) -{ - struct AST_Event *ret; - - ret=malloc(sizeof(struct AST_Event)); - ret->type=AST_TYPE_EVENT; - ret->id=id; - - return ret; -} -struct AST_States* get_ast_states(struct Queue *states) -{ - struct AST_States *ret; - struct AST_State *hold_state; - - /*perhaps no states error should be handled here*/ - assert(states && states->size>0); - - ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size])); - ret->type=AST_TYPE_STATES; - ret->number_of_states=states->size; - ret->states_map=malloc(sizeof(struct Map)); - - Map_Init(ret->states_map); - - while(states->size>0) - { - hold_state=Queue_Pop(states); - Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state); - ret->states[states->size]=hold_state; - } - - assert(states->size==0); - free(states); - - return ret; -} -struct AST_Events* get_ast_events(struct Queue *events) -{ - struct AST_Events *ret; - struct AST_Event *hold_event; - - /*perhaps no events error should be handled here*/ - assert(events && events->size>0); - - ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size])); - ret->type=AST_TYPE_EVENTS; - ret->number_of_events=events->size; - ret->events_map=malloc(sizeof(struct Map)); - - Map_Init(ret->events_map); - - while(events->size>0) - { - hold_event=Queue_Pop(events); - Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event); - ret->events[events->size]=hold_event; - } - - assert(events->size==0); - free(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 *ret; - ret=malloc(sizeof(struct AST_Transition)); - ret->type=AST_TYPE_TRANSITION; - ret->from=from; - ret->to=to; - ret->event=event; - ret->pipeline=pipeline; - - return ret; -} -struct AST_Command* get_ast_command(struct token *function_name,struct token *argument) -{ - struct AST_Command *ret; - ret=malloc(sizeof(struct AST_Command)); - ret->type=AST_TYPE_COMMAND; - ret->function_name=function_name; - ret->argument=argument; - - return ret; -} -struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline) -{ - struct AST_Pipeline *ret; - - ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size])); - ret->type=AST_TYPE_PIPELINE; - ret->size=pipeline->size; - pointer_array_fill((void**)ret->pipeline,pipeline); - - assert(pipeline->size==0); - free(pipeline); - - return ret; -} -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_Machine *ret; - - ret=malloc(sizeof(struct AST_Machine)); - ret->type=AST_TYPE_MACHINE; - ret->id=id; - ret->states=states; - ret->events=events; - ret->transitions=transitions; - - return ret; -} -struct AST_Transitions* get_ast_transitions(struct Queue *transitions) -{ - struct AST_Transitions *ret; - ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size])); - ret->type=AST_TYPE_TRANSITIONS; - ret->size=transitions->size; - - pointer_array_fill((void**)ret->transitions,transitions); - - assert(transitions->size==0); - free(transitions); - - return ret; -} -void delete_ast(struct AST* ast) -{ - switch(ast->type) - { - case AST_TYPE_MACHINE: - delete_ast_machine((struct AST_Machine*)ast); - break; - case AST_TYPE_STATE: - delete_ast_state((struct AST_State*)ast); - break; - case AST_TYPE_STATES: - delete_ast_states((struct AST_States*)ast); - break; - case AST_TYPE_EVENT: - delete_ast_event((struct AST_Event*)ast); - break; - case AST_TYPE_EVENTS: - delete_ast_events((struct AST_Events*)ast); - break; - case AST_TYPE_TRANSITION: - delete_ast_transition((struct AST_Transition*)ast); - break; - case AST_TYPE_TRANSITIONS: - delete_ast_transitions((struct AST_Transitions*)ast); - break; - case AST_TYPE_COMMAND: - delete_ast_command((struct AST_Command*)ast); - break; - case AST_TYPE_PIPELINE: - delete_ast_pipeline((struct AST_Pipeline*)ast); - break; - } -} -void delete_ast_event(struct AST_Event* ast) -{ - if(ast==NULL)return; - delete_token(ast->id); - free(ast); -} -void delete_ast_states(struct AST_States* ast) -{ - size_t i; - if(ast==NULL)return; - for(i=0;i<ast->number_of_states;++i) - delete_ast_state(ast->states[i]); - free(ast); -} -void delete_ast_events(struct AST_Events* ast) -{ - size_t i; - if(ast==NULL)return; - for(i=0;i<ast->number_of_events;++i) - delete_ast_event(ast->events[i]); - free(ast); -} -void delete_ast_transition(struct AST_Transition* ast) -{ - if(ast==NULL)return; - if(ast->pipeline!=NULL) - delete_ast_pipeline(ast->pipeline); - free(ast); -} -void delete_ast_command(struct AST_Command* ast) -{ - if(ast==NULL)return; - delete_token(ast->function_name); - if(ast->argument!=NULL) - delete_token(ast->argument); - free(ast); -} -void delete_ast_pipeline(struct AST_Pipeline* ast) -{ - size_t i; - if(ast==NULL)return; - for(i=0;i<ast->size;++i) - delete_ast_command(ast->pipeline[i]); - free(ast); -} -void delete_ast_machine(struct AST_Machine* ast) -{ - if(ast==NULL)return; - if(ast->id!=NULL) - delete_token(ast->id); - if(ast->states!=NULL) - delete_ast_states(ast->states); - if(ast->events!=NULL) - delete_ast_events(ast->events); - if(ast->transitions!=NULL) - delete_ast_transitions(ast->transitions); -} -void delete_ast_transitions(struct AST_Transitions* ast) -{ - size_t i; - if(ast==NULL)return; - for(i=0;i<ast->size;++i) - delete_ast_transition(ast->transitions[i]); - free(ast); -} -void delete_ast_state(struct AST_State* ast) -{ - if(ast==NULL)return; - if(ast->id!=NULL) - delete_token(ast->id); - free(ast); -} -void pointer_array_fill(void **array,struct Queue *q) -{ - size_t i; - for(i=0;q->size>0;++i) - array[i]=Queue_Pop(q); -} - -struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim) -{ - struct Queue *q; - struct AST* hold_ast; - - q=malloc(sizeof(struct Queue)); - Queue_Init(q); - while(hold_ast=parser(translation_data)) - { - Queue_Push(q,hold_ast); - if(!get_and_check(translation_data,delim)) - break; - } - return q; -} - -#endif |