F diff --git a/README.txt b/README.txt new file mode 100644 --- /dev/null +++ b/README.txt+ Options:+ --print-tokens+ --print-ast+ --print-c+ -o+ --output+ filename+ --extern-queue+ --extern-buffer+ --extern-mutexF diff --git a/src/backend/backend.c b/src/backend/backend.c --- a/src/backend/backend.c +++ b/src/backend/backend.cfor(i=0;i<machine->transitions->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)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{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;}}F diff --git a/src/backend/targets/C/ast_to_c.c b/src/backend/targets/C/ast_to_c.c --- a/src/backend/targets/C/ast_to_c.c +++ b/src/backend/targets/C/ast_to_c.c#include <ast_to_c.h>#include <print.h>- 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;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);}}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)fprintf(out,"#include<stdlib.h>\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;i<translation_unit->number_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;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;i<translation_unit->number_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){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)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;i<vector->number_of_transitions;++i){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*/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);}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){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""\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");"\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(machine<MACHINES_ENUM_END)""\n\t{"- "\n\t\tmachine_states[machine](event,input);"+ );+ if(options->has_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;i<size;++i)\n"- "\t\tret->buffer[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){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;i<size;++i)\n"+ "\t\tret->buffer[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"+ );+ }#endifF diff --git a/src/backend/targets/C/ast_to_c.h b/src/backend/targets/C/ast_to_c.h --- a/src/backend/targets/C/ast_to_c.h +++ b/src/backend/targets/C/ast_to_c.h#include <stdio.h>#include <parser.h>#include <backend.h>+ #include <program.h>#include <ctype.h>#include <stdio.h>#include <string.h>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);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);F diff --git a/src/backend/targets/print/print.c b/src/backend/targets/print/print.c --- a/src/backend/targets/print/print.c +++ b/src/backend/targets/print/print.ccase KW_ELSE:printf("KW_ELSE");break;+ case KW_GRANTED:+ printf("KW_GRANTED");+ break;default:printf("LEXERROR");}F diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c --- a/src/frontend/lexer.c +++ b/src/frontend/lexer.creturn 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);F diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.hKW_NOT,KW_IF,KW_ELSE,+ KW_GRANTED,};struct token{F diff --git a/src/frontend/parser.c b/src/frontend/parser.c --- a/src/frontend/parser.c +++ b/src/frontend/parser.cstruct 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));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;}}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;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;}}elseerror_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;}/*}else{- return get_ast_states(ids);+ return get_ast_states(ids,translation_data);}}/*}}/*- * 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)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))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; }}/*+ * 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 ]*/struct AST* parse_statement(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)}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))if(hold_else==NULL){push_parsing_error("expected a statement after else",translation_data);- delete_ast(hold_expression);- delete_ast(hold_body);return NULL;}}}else{push_parsing_error("expected body statement in if",translation_data);- if(hold_expression)- delete_ast(hold_expression);return NULL;}}elsereturn 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;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;i<ret->number_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;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));ret->from=from;ret->to=to;ret->event=event;+ ret->granted=granted;ret->statement=statement;return ret;F diff --git a/src/frontend/parser.h b/src/frontend/parser.h --- a/src/frontend/parser.h +++ b/src/frontend/parser.hstruct AST_State *from;struct AST_State *to;struct AST_Event *event;+ struct AST *granted;struct AST *statement;};struct AST_Commandstruct 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);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);F diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.cprint_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);}F diff --git a/src/program/program.c b/src/program/program.c --- a/src/program/program.c +++ b/src/program/program.cfile=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);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;i<argc;++i){ret->target=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(++i<argc)ret->output_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{F diff --git a/src/program/program.h b/src/program/program.h --- a/src/program/program.h +++ b/src/program/program.h{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;};F diff --git a/tests/.test6.swp b/tests/.test6.swp deleted file mode 100644B Binary files a/tests/.test6.swp and /dev/null differF diff --git a/tests/test6 b/tests/test6 --- a/tests/test6 +++ b/tests/test6starting 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.Aif !light_bulb.light_onexecute kek;+ else+ execute zeh | kek;];];+ machine temp_switch2+ [+ states [A,B];+ events [A];+ starting on A;+ transitions+ [+ from A to A on event A;+ ];++ ];