diff options
Diffstat (limited to 'src/frontend')
-rw-r--r-- | src/frontend/lexer.c | 160 | ||||
-rw-r--r-- | src/frontend/lexer.h | 54 | ||||
-rw-r--r-- | src/frontend/parser.c | 669 | ||||
-rw-r--r-- | src/frontend/parser.h | 124 |
4 files changed, 1007 insertions, 0 deletions
diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c new file mode 100644 index 0000000..6dc348d --- /dev/null +++ b/src/frontend/lexer.c @@ -0,0 +1,160 @@ +#ifndef LEXER_C +#define LEXER_C +#include <lexer.h> + +#define IS_ID_CHAR(x) ( (x <= 'z' && x>='a') || ( x <= 'Z' && x >= 'A' ) || x=='_') +#define IS_DIGIT(x) ( x <= '9' && x >= '0' ) +#define IS_ID_THING(x) ( IS_ID_CHAR(x) || IS_DIGIT(x)) +#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 + */ +void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data) +{ + skip_white_space(src); + while(src->where_in_src<src->src_size) + { + Queue_Push(token_destination,lex_step(src,translation_data)); + if(has_new_errors(translation_data)) + return; + else + skip_white_space(src); + } + Queue_Push(token_destination,get_token(NULL,0,KW_EOF,src->current_row,src->current_column)); +} + + +struct token* lex_step(struct Source *src,struct Translation_Data *translation_data) +{ + if(check_and_move_if_on_word("machine",sizeof("machine")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("machine")+1,sizeof("machine")-1,KW_MACHINE,src->current_row,src->current_column); + if(check_and_move_if_on_word("from",sizeof("from")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("from")+1,sizeof("from")-1,KW_FROM,src->current_row,src->current_column); + if(check_and_move_if_on_word("to",sizeof("to")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("to")+1,sizeof("to")-1,KW_TO,src->current_row,src->current_column); + if(check_and_move_if_on_word("on",sizeof("on")-1,src,1)) + 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_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_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("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)) + return get_token(src->src+src->where_in_src-sizeof("states")+1,sizeof("states")-1,KW_STATES,src->current_row,src->current_column); + if(check_and_move_if_on_word("events",sizeof("events")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("events")+1,sizeof("events")-1,KW_EVENTS,src->current_row,src->current_column); + if(check_and_move_if_on_word("execute",sizeof("execute")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("execute")+1,sizeof("execute")-1,KW_EXECUTE,src->current_row,src->current_column); + if(check_and_move_if_on_word("event",sizeof("event")-1,src,1)) + 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(IS_ID_CHAR(src->src[src->where_in_src])) /*check for id*/ + { + size_t i; + + ++src->where_in_src; + for( i=src->where_in_src ; + i < src->src_size && IS_ID_THING(src->src[i]); + ++i); + + + i-=src->where_in_src; + src->where_in_src+=i; + return get_token(src->src + src->where_in_src - i - 1, i + 1, KW_ID,src->current_row,src->current_column); + }else if(src->src[src->where_in_src]=='"') /*check for string literal*/ + { + size_t i; + ++src->where_in_src; + for( i=src->where_in_src ; + src->src[i]!='"' && i< src->src_size; + ++i); + + if(i==src->src_size) + { + LEX_ERROR("Unexpected end of file"); + }else + { + i-=src->where_in_src; + src->where_in_src+=i+1; + return get_token(src->src + src->where_in_src-i-1, i, KW_STRING,src->current_row,src->current_column); + } + + }else + { + LEX_ERROR("Unexpected symbol"); + } +} +struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column) +{ + struct token *ret; + ret=malloc(sizeof(struct token)); + ret->data=data; + ret->size=size; + ret->type=type; + ret->row=row; + ret->column=column; + + return ret; +} +void delete_token(struct token *token) +{ + free(token); +} + +/*word_size without the ending '\0' */ +static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after) +{ + size_t i; + if(src->where_in_src + word_size > src->src_size) + return 0; + + for(i=0;i<word_size && word[i]==src->src[src->where_in_src+i];++i); + + if(i<word_size) + { + return 0; + } + else if( (needs_space_after && isspace(src->src[src->where_in_src+i])) || !needs_space_after ) + { + src->where_in_src+=i; + src->current_column+=i; + return 1; + } + else + { + return 0; + } +} +void skip_white_space(struct Source *src) +{ + while(src->where_in_src<src->src_size && isspace(src->src[src->where_in_src])) + { + if(src->src[src->where_in_src]=='\n') + { + ++src->current_row; + src->current_column=0; + } + ++src->where_in_src; + } +} + +void push_token_into_map(struct token *token,struct Map *map,void *thing) +{ + Map_Push(map,token->data,token->size,thing); +} +#endif diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h new file mode 100644 index 0000000..320146c --- /dev/null +++ b/src/frontend/lexer.h @@ -0,0 +1,54 @@ +#ifndef LEXER_H +#define LEXER_H +#include <ctype.h> //isspace +#include <program.h> +#include <queue.h> +#include <map.h> + +struct Translation_Data; +struct Source; + +enum Keyword +{ + KW_MACHINE, + KW_FROM, + KW_TO, + KW_ON, + KW_ID, + KW_STRING, + KW_NOP, + KW_EOF, + KW_OPEN_SQUARE, + KW_CLOSE_SQUARE, + KW_PIPE, + KW_SEMI_COLUMN, + KW_STARTING, + KW_STATES, + KW_EVENTS, + KW_EVENT, + KW_EXECUTE, + KW_TRANSITIONS, + KW_COMMA, +}; +struct token +{ + size_t size; + enum Keyword type; + char *data; + size_t row; + size_t column; +}; + +void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data); +struct token* lex_step(struct Source *src,struct Translation_Data *translation_data); +struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column); +void skip_white_space(struct Source *src); + +void push_token_into_map(struct token *token,struct Map *map,void *thing); + + +void delete_token(struct token *token); +/*:X*/ +static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after); + +#endif diff --git a/src/frontend/parser.c b/src/frontend/parser.c new file mode 100644 index 0000000..3e4e449 --- /dev/null +++ b/src/frontend/parser.c @@ -0,0 +1,669 @@ +#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 diff --git a/src/frontend/parser.h b/src/frontend/parser.h new file mode 100644 index 0000000..ef82184 --- /dev/null +++ b/src/frontend/parser.h @@ -0,0 +1,124 @@ +#ifndef PARSER_H +#define PARSER_H PARSER_H +#include <program.h> +#include <stddef.h> +#include <assert.h> +#include <map.h> + +enum AST_Type +{ + AST_TYPE_MACHINE, + AST_TYPE_STATE, + AST_TYPE_STATES, + AST_TYPE_EVENT, + AST_TYPE_EVENTS, + AST_TYPE_TRANSITION, + AST_TYPE_TRANSITIONS, + AST_TYPE_COMMAND, + AST_TYPE_PIPELINE, +}; +struct AST +{ + enum AST_Type type; +}; +struct AST_State +{ + enum AST_Type type; + struct token *id; +}; +struct AST_Event +{ + enum AST_Type type; + struct token *id; +}; +struct AST_States +{ + enum AST_Type type; + size_t number_of_states; + struct Map *states_map; + struct AST_State *states[]; +}; +struct AST_Events +{ + enum AST_Type type; + size_t number_of_events; + struct Map *events_map; + struct AST_Event *events[]; +}; +struct AST_Transition +{ + enum AST_Type type; + struct AST_State *from; + struct AST_State *to; + struct AST_Event *event; + struct AST_Pipeline *pipeline; +}; +struct AST_Command +{ + enum AST_Type type; + struct token *function_name; + struct token *argument; +}; +struct AST_Pipeline +{ + enum AST_Type type; + size_t size; + struct AST_Command *pipeline[]; +}; +struct AST_Machine +{ + enum AST_Type type; + struct token *id; + struct AST_States *states; + struct AST_Events *events; + struct AST_Transitions *transitions; +}; +struct AST_Transitions +{ + enum AST_Type type; + size_t size; + struct AST_Transition *transitions[]; +}; + + +struct AST* parse_unit(struct Translation_Data *translation_data); +struct AST_Machine* parse_machine(struct Translation_Data *translation_data); +struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data); +struct AST_States* parse_states_inner(struct Translation_Data *translation_data); +struct AST_State* parse_state(struct Translation_Data *translation_data); +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_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_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_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); + + +void delete_ast(struct AST* ast); +void delete_ast_event(struct AST_Event* ast); +void delete_ast_states(struct AST_States* ast); +void delete_ast_state(struct AST_State* ast); +void delete_ast_events(struct AST_Events* ast); +void delete_ast_transition(struct AST_Transition* ast); +void delete_ast_command(struct AST_Command* ast); +void delete_ast_pipeline(struct AST_Pipeline* ast); +void delete_ast_machine(struct AST_Machine* ast); +void delete_ast_transitions(struct AST_Transitions* 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); + +#endif |