From c875f8795586056a676e8a643a44211041ce44d2 Mon Sep 17 00:00:00 2001 From: Galin Simeonov Date: Fri, 4 Jun 2021 22:49:33 +0300 Subject: various stuffs --- README.txt | 10 ++ src/backend/backend.c | 10 +- src/backend/targets/C/ast_to_c.c | 231 ++++++++++++++++++++++++++++++-------- src/backend/targets/C/ast_to_c.h | 19 +++- src/backend/targets/print/print.c | 3 + src/frontend/lexer.c | 3 +- src/frontend/lexer.h | 1 + src/frontend/parser.c | 79 ++++++++----- src/frontend/parser.h | 7 +- src/main.c | 2 +- src/program/program.c | 27 ++++- src/program/program.h | 3 + tests/.test6.swp | Bin 12288 -> 0 bytes tests/test6 | 15 ++- 14 files changed, 319 insertions(+), 91 deletions(-) create mode 100644 README.txt delete mode 100644 tests/.test6.swp diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..66aa403 --- /dev/null +++ b/README.txt @@ -0,0 +1,10 @@ +Options: +--print-tokens +--print-ast +--print-c +-o +--output +filename +--extern-queue +--extern-buffer +--extern-mutex diff --git a/src/backend/backend.c b/src/backend/backend.c index ff9d0bf..b6b78bd 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -99,11 +99,12 @@ void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *un for(i=0;itransitions->size;++i) { machine->transitions->transitions[i]->statement=anotate_statement(machine->transitions->transitions[i]->statement,unit,machine,translation_data); + if(machine->transitions->transitions[i]->granted) + machine->transitions->transitions[i]->granted=anotate_expression(machine->transitions->transitions[i]->granted,unit,machine,translation_data); } if(has_new_errors(translation_data)) { push_error_with_token("in machine",machine->id,translation_data); - delete_ast_machine(machine); } } struct AST* anotate_statement(struct AST *statement,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data) @@ -134,7 +135,10 @@ struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Uni if(hold_machine==NULL) { push_error_with_token("machine id is undefined",((struct AST_Unchecked_State*)hold_left)->name,translation_data); - delete_ast(expression); + return NULL; + }else if(hold_machine==current_machine) + { + push_error_with_token("using a state from the current machine is disallowed",((struct AST_Unchecked_State*)hold_left)->name,translation_data); return NULL; }else { @@ -142,12 +146,10 @@ struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Uni if(hold_left) { ((struct AST_State*)hold_left)->parent=hold_machine; - delete_ast(hold_right); return hold_left; }else { push_error_with_token("state id from foreign machine is undefined",((struct AST_Unchecked_State*)hold_right)->name,translation_data); - delete_ast(hold_right); return NULL; } } diff --git a/src/backend/targets/C/ast_to_c.c b/src/backend/targets/C/ast_to_c.c index 9c8b38d..76ebbfd 100644 --- a/src/backend/targets/C/ast_to_c.c +++ b/src/backend/targets/C/ast_to_c.c @@ -3,7 +3,7 @@ #include #include -void ast_to_c(char *output_name,struct AST_Translation_Unit *tree) +void ast_to_c(char *output_name,struct AST_Translation_Unit *tree,struct Options *options) { size_t output_name_length; char *hold_name; @@ -18,26 +18,26 @@ void ast_to_c(char *output_name,struct AST_Translation_Unit *tree) memcpy(hold_name+output_name_length,".h",sizeof(".h")); hold_out=fopen(hold_name,"w"); - ast_translation_unit_to_c_print_header_part(hold_out,output_name,(struct AST_Translation_Unit*)tree); + ast_translation_unit_to_c_print_header_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options); fclose(hold_out); memcpy(hold_name+output_name_length,".c",sizeof(".c")); hold_out=fopen(hold_name,"w"); - ast_translation_unit_to_c_print_body_part(hold_out,output_name,(struct AST_Translation_Unit*)tree); + ast_translation_unit_to_c_print_body_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options); fclose(hold_out); memcpy(hold_name+output_name_length,"_external.h",sizeof("_external.h")); hold_out=fopen(hold_name,"w"); - ast_translation_unit_to_c_print_external_commands(hold_out,output_name,(struct AST_Translation_Unit*)tree); + ast_translation_unit_to_c_print_external_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options); fclose(hold_out); free(hold_name); }else { - ast_translation_unit_to_c_print_external_commands(stdout,NULL,(struct AST_Translation_Unit*)tree); - ast_translation_unit_to_c_print_header_part(stdout,NULL,(struct AST_Translation_Unit*)tree); - ast_translation_unit_to_c_print_body_part(stdout,NULL,(struct AST_Translation_Unit*)tree); + ast_translation_unit_to_c_print_external_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options); + ast_translation_unit_to_c_print_header_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options); + ast_translation_unit_to_c_print_body_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options); } } @@ -63,7 +63,7 @@ void ast_translation_unit_to_c_print_footer_string(FILE *out,char *base_name,cha ast_translation_unit_to_c_print_base_name(out,base_name); fprintf(out,"%s",file_suffix); } -void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit) +void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options) { size_t i; if(base_name) @@ -72,17 +72,16 @@ void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struc fprintf(out,"#include\n\n"); } - ast_to_c_print_internal_stuff_for_header(out,translation_unit); + ast_to_c_print_internal_stuff_for_header(out,translation_unit,options); for(i=0;inumber_of_machines;++i) ast_machine_to_c_make_header_part(out,translation_unit->machines[i]); - ast_machines_to_c_array(out,translation_unit); if(base_name) ast_translation_unit_to_c_print_footer_string(out,base_name,"_H"); } -void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit) +void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options) { size_t i; @@ -93,15 +92,16 @@ void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct fprintf(out,"#include \"%s_external.h\"\n\n",base_name); } + ast_machines_to_c_array(out,translation_unit); + ast_to_c_print_internal_stuff_for_body(out,options); for(i=0;inumber_of_machines;++i) ast_machine_to_c_make_body_part(out,translation_unit->machines[i]); - ast_to_c_print_internal_stuff_for_body(out); if(base_name) ast_translation_unit_to_c_print_footer_string(out,base_name,"_C"); } -void ast_translation_unit_to_c_print_external_commands(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit) +void ast_translation_unit_to_c_print_external_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options) { if(base_name) { @@ -109,6 +109,22 @@ void ast_translation_unit_to_c_print_external_commands(FILE *out,char *base_name fprintf(out,"#include \"%s.h\"\n\n",base_name); } + if(options->providing_own_queue_implementation) + { + fprintf(out, "extern void machine_push_to_global_event_queue(machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine);\n"); + fprintf(out, "extern void machine_pop_from_global_event_queue();\n"); + fprintf(out, "extern struct machine_queue_t machine_queue_global;\n"); + } + if(options->providing_own_buffer_implementation) + { + fprintf(out, "extern machine_buffer_t* get_machine_buffer(void *content,size_t size);\n"); + fprintf(out, "\nextern void delete_machine_buffer(machine_buffer_t *buffer);\n"); + } + if(options->has_mutex) + { + fprintf(out, "extern void machine_mutex_lock(machine_buffer_t *input,int event, enum MACHINES_ENUM target_machine); \n"); + fprintf(out, "extern void machine_mutex_unlock(int event, enum MACHINES_ENUM target_machine); \n"); + } Map_Map_Extended(translation_unit->used_commands_map,(void (*)(void*,void*))ast_command_to_c_extern_declaration,out); if(base_name) @@ -178,10 +194,12 @@ void ast_states_to_c(FILE *out,struct AST_Machine *machine) void ast_transitions_of_state_to_c(FILE *out,struct AST_Machine *machine,struct State_And_Transitions *vector) { size_t i; + short indentation=3; //fprintf(out,"\tmachine_buffer_t *hold_buffer;\n\thold_buffer=input;\n\n"); if(vector->number_of_transitions>0) { + fprintf(out,"\n\tmachine_states_lock=1;\n"); fprintf(out,"\tswitch(event)\n\t{\n"); for(i=0;inumber_of_transitions;++i) { @@ -189,17 +207,33 @@ void ast_transitions_of_state_to_c(FILE *out,struct AST_Machine *machine,struct ast_event_to_c_enum(out,machine,vector->transitions[i]->event); fprintf(out,":\n"); + if(vector->transitions[i]->granted) + { + fprintf(out,"\t\t\tif("); + ast_expression_to_c(out,vector->transitions[i]->granted); + fprintf(out,")\n\t\t\t{\n"); + indentation++; + } + //ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline); - ast_statement_to_c(out,3,vector->transitions[i]->statement); - fprintf(out,"\t\t\tmachine_states["); + ast_statement_to_c(out,indentation,vector->transitions[i]->statement); + ast_to_c_print_tabs(out,indentation); + fprintf(out,"machine_states["); ast_token_to_c(out,machine->id); fprintf(out,"]="); ast_state_to_c_function_name(out,machine,vector->transitions[i]->to); - fprintf(out,";\n\t\t\tbreak;\n"); + fprintf(out,";\n"); + ast_to_c_print_tabs(out,indentation); + fprintf(out,"break;\n"); + if(vector->transitions[i]->granted) + { + fprintf(out,"\t\t\t}\n"); + } } fprintf(out,"\t}\n"); } fprintf(out,"\tdelete_machine_buffer(input);\n"); + fprintf(out,"\n\tmachine_states_lock=0;"); } /*prints the enum tag for the given machine*/ @@ -246,7 +280,13 @@ void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer) if(command->argument==NULL) fprintf(out,"NULL"); else + { + fprintf(out,"get_machine_buffer(\""); + ast_token_to_c(out,command->argument); + fprintf(out,"\",sizeof(\""); ast_token_to_c(out,command->argument); + fprintf(out,"\"))"); + } fprintf(out,",%s)",hold_buffer); } @@ -273,6 +313,8 @@ void ast_machines_to_c_array(FILE *out,struct AST_Translation_Unit *translation_ fprintf(out,","); } fprintf(out,"};\n"); + + fprintf(out,"_Bool machine_states_lock=0;\n"); } void ast_machines_to_c_enum(FILE *out,struct AST_Translation_Unit *translation_unit) { @@ -300,16 +342,21 @@ void ast_event_to_c_enum(FILE *out,struct AST_Machine *machine,struct AST_Event fprintf(out,"_EVENT_"); ast_token_to_c(out,event->name); } -void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit) +void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit,struct Options *options) { fprintf(out,"\n\n"); ast_machines_to_c_enum(out,translation_unit); fprintf(out,"\n\n"); - - ast_to_c_print_comment(out,"\tthis is the structure that facilitates data exchange"); - fprintf(out,"typedef struct machine_buffer_t \n{" - "\n\tsize_t size;\n\tunsigned char buffer[];\n} machine_buffer_t;\n\n"); + if(options->providing_own_buffer_implementation) + { + fprintf(out,"typedef struct machine_buffer_t machine_buffer_t\t\n"); + }else + { + ast_print_machine_buffer_declarations(out); + } + if(!options->providing_own_queue_implementation) + ast_to_c_print_event_queue_declaration(out); ast_to_c_print_comment(out, "\tuse this function to pass an event to a machine\n" @@ -319,7 +366,7 @@ void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_U "\tinput can be NULL" ); - fprintf(out,"void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input);\n\n"); + fprintf(out,"extern void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input);\n\n"); @@ -329,41 +376,40 @@ void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_U "\tsize is in bytes" ); - fprintf(out,"machine_buffer_t* get_machine_buffer(void *content,size_t size);\n\n"); - ast_to_c_print_comment(out,"\tfrees the buffer from the heap"); - fprintf(out,"void delete_machine_buffer(machine_buffer_t *buffer);\n\n"); + } -void ast_to_c_print_internal_stuff_for_body(FILE *out) +void ast_to_c_print_internal_stuff_for_body(FILE *out,struct Options *options) { + if(!options->providing_own_queue_implementation) + ast_to_c_print_event_queue_definition(out); + if(!options->providing_own_buffer_implementation) + ast_print_machine_buffer_definitions(out); + fprintf(out, "void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input)\n" "{\n" "\tif(machinehas_mutex) + fprintf(out,"\t\tmachine_mutex_lock(input,event,machine);\n"); + fprintf(out, + "\n\t\tif(machine_states_lock)" + "\n\t\t{" + "\n\t\t\tmachine_push_to_global_event_queue(input,event,machine);" + "\n\t\t}else" + "\n\t\t{" + "\n\t\t\tmachine_states[machine](event,input);" + "\n\t\t\twhile(machine_queue_global.size>0)machine_pop_from_global_event_queue();" + "\n\t\t}" "\n\t}" + ); + if(options->has_mutex) + fprintf(out,"\t\tmachine_mutex_unlock(event,machine);\n"); + fprintf(out, "\n}\n" ); - fprintf(out, "machine_buffer_t* get_machine_buffer(void *content,size_t size)\n" - "{\n" - "\tmachine_buffer_t *ret;\n" - "\tsize_t i;\n" - "\t\n" - "\tret=malloc(sizeof(machine_buffer_t)+size);\n" - "\tret->size=size;\n" - "\tfor(i=0;ibuffer[i]=((unsigned char*)content)[i];\n" - "\treturn ret;\n" - "}\n"); - - fprintf(out, "\nvoid delete_machine_buffer(machine_buffer_t *buffer)\n" - "{\n" - "\tif(buffer)\n" - "\t{\n" - "\t\tfree(buffer);\n" - "\t}\n}" - ); } void ast_to_c_print_comment(FILE *out,char *comment) { @@ -444,4 +490,97 @@ void ast_expression_state_to_c(FILE *out,struct AST_State *state) ast_state_to_c_function_name(out,state->parent,state); } +void ast_to_c_print_event_queue_declaration(FILE *out) +{ + ast_to_c_print_comment(out, "\tthis queue is used when an event is received for a machine that is\n" + "\tcurrently in transit\n" + "\tdoes not guarantee any thread safety,\n" + "\tbut preserves intuitive order of execution\n" + "\tdo not use these manually" + ); + fprintf(out, "struct machine_queue_node_t\n" + "{\n" + "\tstruct machine_queue_node_t *prev;\n" + "\tmachine_buffer_t *input;\n" + "\tint event;\n" + "\tenum MACHINES_ENUM target_machine;\n" + "};\n" + ); + fprintf(out, "struct machine_queue_t\n" + "{\n" + "\tstruct machine_queue_node_t *first,*last;\n" + "\tsize_t size;\n" + "};\n" + ); + fprintf(out, "extern void machine_push_to_global_event_queue(machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine);\n"); + fprintf(out, "extern void machine_pop_from_global_event_queue();\n"); +} +void ast_to_c_print_event_queue_definition(FILE *out) +{ + fprintf(out, "struct machine_queue_t machine_queue_global = { .first=NULL,.last=NULL,.size=0};\n"); + fprintf(out, "void machine_push_to_global_event_queue(machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine)\n" + "{\n" + "\tif(machine_queue_global.size==0)\n" + "\t{\n" + "\t\tmachine_queue_global.first=machine_queue_global.last=malloc(sizeof(struct machine_queue_node_t));\n" + "\t\tmachine_queue_global.last->input=input;\n" + "\t\tmachine_queue_global.last->event=event;\n" + "\t\tmachine_queue_global.last->target_machine=target_machine;\n" + "\t\tmachine_queue_global.size=1;\n" + "\t}else\n" + "\t{\n" + "\t\tmachine_queue_global.last=machine_queue_global.last->prev=malloc(sizeof(struct machine_queue_node_t));\n" + "\t\tmachine_queue_global.last->input=input;\n" + "\t\tmachine_queue_global.last->event=event;\n" + "\t\tmachine_queue_global.last->target_machine=target_machine;\n" + "\t\t++machine_queue_global.size;\n" + "\t}\n" + "}\n" + + ); + + fprintf(out, "void machine_pop_from_global_event_queue()\n" + "{\n" + "\tstruct machine_queue_node_t *hold_node;\n" + "\thold_node=machine_queue_global.first;\n" + "\tmachine_queue_global.first=machine_queue_global.first->prev;\n" + "\tif(--machine_queue_global.size==0)\n" + "\t\tmachine_queue_global.last=NULL;\n" + "\tmachine_states[hold_node->target_machine](hold_node->event,hold_node->input);\n" + "\tfree(hold_node);\n" + "}\n" + ); +} +void ast_print_machine_buffer_declarations(FILE *out) +{ + ast_to_c_print_comment(out,"\tthis is the structure that facilitates data exchange"); + fprintf(out,"typedef struct machine_buffer_t \n{" + "\n\tsize_t size;\n\tunsigned char buffer[];\n} machine_buffer_t;\n\n"); + + fprintf(out,"extern machine_buffer_t* get_machine_buffer(void *content,size_t size);\n\n"); + ast_to_c_print_comment(out,"\tfrees the buffer from the heap"); + fprintf(out,"extern void delete_machine_buffer(machine_buffer_t *buffer);\n\n"); +} +void ast_print_machine_buffer_definitions(FILE *out) +{ + fprintf(out, "machine_buffer_t* get_machine_buffer(void *content,size_t size)\n" + "{\n" + "\tmachine_buffer_t *ret;\n" + "\tsize_t i;\n" + "\t\n" + "\tret=malloc(sizeof(machine_buffer_t)+size);\n" + "\tret->size=size;\n" + "\tfor(i=0;ibuffer[i]=((unsigned char*)content)[i];\n" + "\treturn ret;\n" + "}\n"); + + fprintf(out, "\nvoid delete_machine_buffer(machine_buffer_t *buffer)\n" + "{\n" + "\tif(buffer)\n" + "\t{\n" + "\t\tfree(buffer);\n" + "\t}\n}\n" + ); +} #endif diff --git a/src/backend/targets/C/ast_to_c.h b/src/backend/targets/C/ast_to_c.h index 299d6db..76b556c 100644 --- a/src/backend/targets/C/ast_to_c.h +++ b/src/backend/targets/C/ast_to_c.h @@ -3,21 +3,23 @@ #include #include #include +#include #include #include #include struct State_And_Transitions; -void ast_to_c(char *output_name,struct AST_Translation_Unit *tree); +void ast_to_c(char *output_name,struct AST_Translation_Unit *tree,struct Options *options); -void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit); -void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit); -void ast_translation_unit_to_c_print_external_commands(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit); +void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options); +void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options); +void ast_translation_unit_to_c_print_external_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options); void ast_translation_unit_to_c_print_base_name(FILE *out, char *base_name); void ast_translation_unit_to_c_print_header_string(FILE *out,char *base_name,char *file_suffix); void ast_translation_unit_to_c_print_footer_string(FILE *out,char *base_name,char *file_suffix); +void ast_translation_unit_to_c_print_external_commands(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit); void ast_translation_unit_to_c(FILE *out,struct AST_Translation_Unit *translation_unit); void ast_machine_to_c(FILE *out,struct AST_Machine *machine); @@ -49,11 +51,16 @@ void ast_if_to_c(FILE *out,size_t indentation,struct AST_If_Statement *statement void ast_expression_to_c(FILE *out,struct AST *expression); void ast_expression_state_to_c(FILE *out,struct AST_State *state); -void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit); -void ast_to_c_print_internal_stuff_for_body(FILE *out); +void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit,struct Options *options); +void ast_to_c_print_internal_stuff_for_body(FILE *out,struct Options *options); void ast_to_c_print_comment(FILE *out,char *comment); +void ast_to_c_print_event_queue_declaration(FILE *out); +void ast_to_c_print_event_queue_definition(FILE *out); + +void ast_print_machine_buffer_declarations(FILE *out); +void ast_print_machine_buffer_definitions(FILE *out); /* :X */ void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs); diff --git a/src/backend/targets/print/print.c b/src/backend/targets/print/print.c index 3c33438..cfe22e9 100644 --- a/src/backend/targets/print/print.c +++ b/src/backend/targets/print/print.c @@ -87,6 +87,9 @@ void print_keyword_enum(enum Keyword code) case KW_ELSE: printf("KW_ELSE"); break; + case KW_GRANTED: + printf("KW_GRANTED"); + break; default: printf("LEXERROR"); } diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c index a832a17..2d9bddd 100644 --- a/src/frontend/lexer.c +++ b/src/frontend/lexer.c @@ -71,9 +71,10 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d return get_token(src->src+src->where_in_src-sizeof("transitions")+1,sizeof("transitions")-1,KW_TRANSITIONS,src->current_row,src->current_column); if(check_and_move_if_on_word("if",sizeof("if")-1,src,1)) return get_token(src->src+src->where_in_src-sizeof("if")+1,sizeof("if")-1,KW_IF,src->current_row,src->current_column); - if(check_and_move_if_on_word("else",sizeof("else")-1,src,1)) return get_token(src->src+src->where_in_src-sizeof("else")+1,sizeof("else")-1,KW_ELSE,src->current_row,src->current_column); + if(check_and_move_if_on_word("granted",sizeof("granted")-1,src,1)) + return get_token(src->src+src->where_in_src-sizeof("granted")+1,sizeof("granted")-1,KW_GRANTED,src->current_row,src->current_column); diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h index 54c88fa..1134739 100644 --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.h @@ -37,6 +37,7 @@ enum Keyword KW_NOT, KW_IF, KW_ELSE, + KW_GRANTED, }; struct token { diff --git a/src/frontend/parser.c b/src/frontend/parser.c index 7af7af2..b38776e 100644 --- a/src/frontend/parser.c +++ b/src/frontend/parser.c @@ -15,6 +15,7 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra struct Map *hold_command_map; struct Map *hold_machines_map; struct AST_Machine *hold_machine; + struct AST_Machine *hold_possible_duplicate; machines=calloc(1,sizeof(struct Queue)); @@ -29,18 +30,22 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra while(!get_and_check(translation_data,KW_EOF)) { hold_machine=parse_machine(translation_data); - /*TODO check for repeated machine ids*/ if(hold_machine) { - Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine); - Queue_Push(machines,hold_machine); + if(hold_possible_duplicate=Map_Check(hold_machines_map,hold_machine->id->data,hold_machine->id->size)) + { + push_error_with_token("duplicate machine name",hold_machine->id,translation_data); + push_error_with_token("conflicts with",hold_possible_duplicate->id,translation_data); + delete_ast_machine(hold_machine); + return NULL; + }else + { + Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine); + Queue_Push(machines,hold_machine); + } } else { - Map_Map(hold_command_map,(void (*)(void*))delete_ast_command); - Map_Destroy(hold_command_map); - while(machines->size>0) - delete_ast_machine(Queue_Pop(machines)); return NULL; } } @@ -64,7 +69,6 @@ struct AST_Machine* parse_machine(struct Translation_Data *translation_data) 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; @@ -76,13 +80,11 @@ struct AST_Machine* parse_machine(struct Translation_Data *translation_data) 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 @@ -232,9 +234,6 @@ struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translat 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; } /* @@ -255,7 +254,7 @@ struct AST_States* parse_states_inner(struct Translation_Data *translation_data) }else { - return get_ast_states(ids); + return get_ast_states(ids,translation_data); } } /* @@ -323,7 +322,7 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla } } /* - * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ] + * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ granted-part ] [ statement-part ] * */ struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events) @@ -333,6 +332,7 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat struct AST_State *hold_to; struct AST_Event *hold_event; struct AST *hold_statement=NULL; + struct AST *hold_granted=NULL; struct token *hold_token; if(get_and_check(translation_data,KW_FROM)) @@ -361,12 +361,13 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat delete_token(hold_token); if(hold_event!=NULL) { - + hold_granted=parse_transition_granted(translation_data,states,events); + 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); + return get_ast_transition(hold_from,hold_to,hold_event,hold_granted,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; } @@ -378,6 +379,20 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat }else { return NULL; } } +/* + * granted-part : 'granted' expression + */ +struct AST* parse_transition_granted(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events) +{ + if(get_and_check(translation_data,KW_GRANTED)) + { + return parse_expression(translation_data); + }else + { + return NULL; + } +} + /* * statement : 'execute' pipeline ; | 'if' expression statement [ else statement ] */ @@ -396,7 +411,6 @@ struct AST* parse_statement(struct Translation_Data *translation_data,struct AST }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)) @@ -411,8 +425,6 @@ struct AST* parse_statement(struct Translation_Data *translation_data,struct AST if(hold_else==NULL) { push_parsing_error("expected a statement after else",translation_data); - delete_ast(hold_expression); - delete_ast(hold_body); return NULL; } } @@ -420,8 +432,6 @@ struct AST* parse_statement(struct Translation_Data *translation_data,struct AST }else { push_parsing_error("expected body statement in if",translation_data); - if(hold_expression) - delete_ast(hold_expression); return NULL; } }else @@ -520,7 +530,7 @@ struct AST_Event* get_ast_event(struct token *id) return ret; } -struct AST_States* get_ast_states(struct Queue *states) +struct AST_States* get_ast_states(struct Queue *states,struct Translation_Data *translation_data) { struct AST_States *ret; struct AST_State *hold_state; @@ -538,8 +548,24 @@ 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); + + if(Map_Check(ret->states_map,hold_state->name->data,hold_state->name->size)) + { + size_t i; + + push_error_with_token("duplicate state in states definition",hold_state->name,translation_data); + + for(i=states->size+1;inumber_of_states;++i) + delete_ast_state(ret->states[i]); + delete_ast_state(hold_state); + while(states->size>0) + delete_ast_state(Queue_Pop(states)); + + return NULL; + }else + { + 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; @@ -578,7 +604,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 *statement) +struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *granted,struct AST *statement) { struct AST_Transition *ret; ret=malloc(sizeof(struct AST_Transition)); @@ -586,6 +612,7 @@ struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_Stat ret->from=from; ret->to=to; ret->event=event; + ret->granted=granted; ret->statement=statement; return ret; diff --git a/src/frontend/parser.h b/src/frontend/parser.h index 4745f63..8845507 100644 --- a/src/frontend/parser.h +++ b/src/frontend/parser.h @@ -62,6 +62,7 @@ struct AST_Transition struct AST_State *from; struct AST_State *to; struct AST_Event *event; + struct AST *granted; struct AST *statement; }; struct AST_Command @@ -135,6 +136,8 @@ 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* parse_transition_granted(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events); + struct AST* parse_statement(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events); struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data); @@ -149,9 +152,9 @@ 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_States* get_ast_states(struct Queue *states,struct Translation_Data *translation_data); 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 *statement); +struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *granted,struct AST *statement); 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); diff --git a/src/main.c b/src/main.c index 1ad3ae6..9467ace 100644 --- a/src/main.c +++ b/src/main.c @@ -52,7 +52,7 @@ int main(int argc,char **argv) print_ast((struct AST*)translation_unit); }else if(options->target==OPTION_TARGET_C) { - ast_to_c(options->output_name,translation_unit); + ast_to_c(options->output_name,translation_unit,options); } delete_ast((struct AST*)translation_unit); } diff --git a/src/program/program.c b/src/program/program.c index 51757a2..09650ec 100644 --- a/src/program/program.c +++ b/src/program/program.c @@ -10,9 +10,15 @@ struct Source* extract_source(char *src_name) file=fopen(src_name,"r"); if(file==NULL) - return NULL; + { + fprintf(stderr,"Could not open source file. "); + exit(1); + } if(fseek(file,0L,SEEK_END)!=0) - return NULL; + { + fprintf(stderr,"Could not open source file. "); + exit(1); + } ret=malloc(sizeof(struct Source)); ret->src_size=ftell(file); @@ -42,6 +48,9 @@ struct Options* parse_command_line(int argc,char **argv) ret->src_name=NULL; ret->output_name=NULL; ret->is_quiet=0; + ret->providing_own_queue_implementation=0; + ret->providing_own_buffer_implementation=0; + ret->has_mutex=0; for(i=0;itarget=OPTION_TARGET_AST; else if(!strncmp(argv[i],"--print-c",sizeof("--print-c"))) ret->target=OPTION_TARGET_C; + else if(!strncmp(argv[i],"--extern-queue",sizeof("--extern-queue"))) + ret->providing_own_queue_implementation=1; + else if(!strncmp(argv[i],"--extern-buffer",sizeof("--extern-buffer"))) + ret->providing_own_buffer_implementation=1; + else if(!strncmp(argv[i],"--extern-mutex",sizeof("--extern-mutex"))) + ret->has_mutex=1; else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output"))) { if(++ioutput_name=argv[i]; else if(!ret->is_quiet) { - fprintf(stderr,"Error: Output filename is too long"); + fprintf(stderr,"Error: Output filename is too long\n"); exit(1); }else { exit(1); } } + }else if(argv[i][0]=='-') + { + fprintf(stderr,"Error: Invalid command line option %s\n",argv[i]); + exit(1); }else if(strnlen(argv[i],101)<100) { ret->src_name=argv[i]; }else if(!ret->is_quiet) { - fprintf(stderr,"Error: Input filename is too long"); + fprintf(stderr,"Error: Input filename is too long\n"); exit(1); }else { diff --git a/src/program/program.h b/src/program/program.h index fea0aef..214e812 100644 --- a/src/program/program.h +++ b/src/program/program.h @@ -33,6 +33,9 @@ struct Options { enum Options_Target_Type target; int is_quiet:1; + int providing_own_queue_implementation:1; + int providing_own_buffer_implementation:1; + int has_mutex:1; char *src_name; char *output_name; }; diff --git a/tests/.test6.swp b/tests/.test6.swp deleted file mode 100644 index dc85c11..0000000 Binary files a/tests/.test6.swp and /dev/null differ diff --git a/tests/test6 b/tests/test6 index 3fed6d3..2b0411e 100644 --- a/tests/test6 +++ b/tests/test6 @@ -19,8 +19,21 @@ machine temp_switch starting on A; transitions [ - from A to B on event A granted !light_bulb.light_on + from A to B on event A granted !light_bulb.light_on || temp_switch2.A if !light_bulb.light_on execute kek; + else + execute zeh | kek; ]; ]; +machine temp_switch2 +[ + states [A,B]; + events [A]; + starting on A; + transitions + [ + from A to A on event A; + ]; + +]; -- cgit v1.2.3