aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGalin Simeonov <gts@volconst.com>2021-06-04 22:49:33 +0300
committerGalin Simeonov <gts@volconst.com>2021-07-15 18:07:29 +0300
commitc875f8795586056a676e8a643a44211041ce44d2 (patch)
tree88bfd4b4923ed30de31b130672dda65e4b18a607
parenta26684a417729699e95b335a3d00798237ffba9b (diff)
downloadMEGATRON-c875f8795586056a676e8a643a44211041ce44d2.tar.gz
various stuffs
-rw-r--r--README.txt10
-rw-r--r--src/backend/backend.c10
-rw-r--r--src/backend/targets/C/ast_to_c.c231
-rw-r--r--src/backend/targets/C/ast_to_c.h19
-rw-r--r--src/backend/targets/print/print.c3
-rw-r--r--src/frontend/lexer.c3
-rw-r--r--src/frontend/lexer.h1
-rw-r--r--src/frontend/parser.c79
-rw-r--r--src/frontend/parser.h7
-rw-r--r--src/main.c2
-rw-r--r--src/program/program.c27
-rw-r--r--src/program/program.h3
-rw-r--r--tests/.test6.swpbin12288 -> 0 bytes
-rw-r--r--tests/test615
14 files changed, 319 insertions, 91 deletions
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;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)
@@ -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 <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;
@@ -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<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;
@@ -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;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)
{
@@ -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;i<vector->number_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(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)
{
@@ -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;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"
+ );
+}
#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 <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);
@@ -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; }
@@ -379,6 +380,20 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat
}
/*
+ * 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)
@@ -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;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;
@@ -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;i<argc;++i)
{
@@ -51,6 +60,12 @@ struct Options* parse_command_line(int argc,char **argv)
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)
@@ -59,19 +74,23 @@ struct Options* parse_command_line(int argc,char **argv)
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
{
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
--- a/tests/.test6.swp
+++ /dev/null
Binary files 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;
+ ];
+
+];