aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGalin Simeonov <gts@volconst.com>2021-06-03 12:38:37 +0300
committerGalin Simeonov <gts@volconst.com>2021-07-15 18:04:02 +0300
commit76fc38b3cdfded2911b464baa7b182b5102318d1 (patch)
tree389223f76086bff07a3cd762683e5a16d34d12d2
parent85b23fbee717f047af5a89eac6f4dba8e7812524 (diff)
downloadMEGATRON-76fc38b3cdfded2911b464baa7b182b5102318d1.tar.gz
work on generated C code
-rw-r--r--src/backend/backend.c116
-rw-r--r--src/backend/backend.h13
-rw-r--r--src/backend/targets/C/ast_to_c.c288
-rw-r--r--src/backend/targets/C/ast_to_c.h36
-rw-r--r--src/frontend/lexer.c18
-rw-r--r--src/frontend/lexer.h7
-rw-r--r--src/frontend/parser.c281
-rw-r--r--src/frontend/parser.h46
-rw-r--r--src/main.c2
-rw-r--r--src/program/program.c7
-rw-r--r--src/program/program.h2
-rw-r--r--tests/test223
-rw-r--r--tests/test326
-rw-r--r--tests/test424
14 files changed, 791 insertions, 98 deletions
diff --git a/src/backend/backend.c b/src/backend/backend.c
index 122e84c..6646e6c 100644
--- a/src/backend/backend.c
+++ b/src/backend/backend.c
@@ -6,6 +6,7 @@
struct State_And_Transitions** extract_transition_table(struct AST_States *states,struct AST_Transitions *transitions)
{
struct State_And_Transitions **ret;
+ struct AST_State *hold_state;
struct Queue *qs;
size_t i;
@@ -18,7 +19,13 @@ struct State_And_Transitions** extract_transition_table(struct AST_States *state
/*traverse transitions and push them into the queue of their coresponding state*/
for(i=0;i<transitions->size;++i)
- Queue_Push(qs+transitions->transitions[i]->from->number,transitions->transitions[i]);
+ {
+ hold_state=extract_state(transitions->transitions[i]->from,states);
+
+ assert(hold_state!=NULL);
+
+ Queue_Push(qs+hold_state->number,transitions->transitions[i]);
+ }
/*condense the queues into the arrays*/
for(i=0;i<states->number_of_states;++i)
@@ -34,4 +41,111 @@ struct State_And_Transitions** extract_transition_table(struct AST_States *state
return ret;
}
+_Bool expression_is_binary(struct AST* expression)
+{
+ return (expression->type==AST_TYPE_OP_OR || expression->type==AST_TYPE_OP_AND);
+}
+_Bool expression_is_unary(struct AST* expression)
+{
+ return (expression->type==AST_TYPE_OP_NOT);
+}
+_Bool state_is_in_states(struct AST_State *state,struct AST_States *states)
+{
+ return state==Map_Check(states->states_map,state->name->data,state->name->size);
+}
+
+struct AST_State* extract_state(struct AST *expression,struct AST_States *states)
+{
+ struct AST_State *hold_state;
+
+ assert(expression->type==AST_TYPE_OP_NOT || expression->type==AST_TYPE_OP_AND || expression->type==AST_TYPE_OP_OR
+ || expression->type==AST_TYPE_STATE );
+
+ if(expression->type==AST_TYPE_STATE)
+ {
+ if(state_is_in_states((struct AST_State*)expression,states))
+ return (struct AST_State*)expression;
+ else
+ return NULL;
+ }else if(expression_is_binary(expression))
+ {
+ hold_state=extract_state(((struct AST_Binary_Expression*)expression)->left,states);
+ if(hold_state)
+ return hold_state;
+ else
+ return extract_state(((struct AST_Binary_Expression*)expression)->right,states);
+ }else
+ {
+ return extract_state(((struct AST_Unary_Expression*)expression)->operand,states);
+ }
+}
+
+_Bool check_expression(struct AST *state,struct AST_Translation_Unit *unit)
+{
+
+}
+_Bool check_transition(struct AST *state,struct AST_Translation_Unit *unit)
+{
+
+}
+void anotate_unchecked_states(struct AST_Translation_Unit *unit,struct Translation_Data *translation_data)
+{
+ size_t i;
+ for(i=0;i<unit->number_of_machines;++i)
+ {
+ anotate_machine(unit->machines[i],unit);
+ }
+ if(has_new_errors(
+
+}
+void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *unit,struct Translation_Data *translation_data)
+{
+ size_t i;
+ for(i=0;i<machine->transitions->size;++i)
+ {
+ machine->transitions->transitions[i]->from=anotate_expression(machine->transitions->transitions[i]->from,machine,unit);
+ }
+ if(has_new_errors(translation_data))
+ {
+ push_error_with_token("in machine",translation_data,machine->id);
+ delete_ast_machine(machine);
+ }
+}
+struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data);
+{
+ struct AST_Machine *hold_machine;
+ struct AST *hold_left;
+ struct AST *hold_right;
+
+ if(expression_is_binary(expression))
+ {
+ left=((struct AST_Binary_Expression*)expression)->left;
+ right=((struct AST_Binary_Expression*)expression)->right;
+
+ if(expression->type==AST_TYPE_OP_SELECTOR)
+ {
+ hold_machine=Map_Check(unit->machines_map,((struct AST_Unchecked_State*)hold_left)->name->data,((struct AST_Unchecked_State*)hold_left)->name->size);
+ 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
+ {
+ return ast_check_state(hold_right,hold_machine->states,translation_data);
+ }
+ }else
+ {
+ AS_BIN_EXPR_PTR(expression)->right=anotate_expression(AS_BIN_EXPR_PTR(expression)->right,machine,unit);
+ AS_BIN_EXPR_PTR(expression)->left=anotate_expression(AS_BIN_EXPR_PTR(expression)->left,machine,unit);
+ return expression;
+ }
+ }else if(expression_is_unary(expression))
+ {
+ AS_UN_EXPR_PTR(expression)->operand=anotate_expression(AS_UN_EXPR_PTR(expression)->operand,machine,unit);
+ }else if(expression->type==AST_TYPE_UNFINISHED_STATE)
+ {
+ return ast_check_state(AS_UNCK_EXPR_PTR(expression),machine->states,translation_data);
+ }
+}
#endif
diff --git a/src/backend/backend.h b/src/backend/backend.h
index 1857cd0..8b865fd 100644
--- a/src/backend/backend.h
+++ b/src/backend/backend.h
@@ -2,6 +2,7 @@
#define BACKEND_H BACKEND_H
#include <parser.h>
#include <ast_to_c.h>
+#include <map.h>
/*
* describes a given state and the transitions coming out of it
@@ -15,4 +16,16 @@ struct State_And_Transitions
};
/*returns an array of state_and_transition structs*/
struct State_And_Transitions** extract_transition_table(struct AST_States *states,struct AST_Transitions *transitions);
+/*extracts a state from the expression that belongs in the states structure*/
+struct AST_State* extract_state(struct AST *expression,struct AST_States *states);
+
+void anotate_unchecked_states(struct AST_Translation_Unit *unit,struct Translation_Data *translation_data);
+void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *unit,struct Translation_Data *translation_data);
+struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data);
+
+_Bool expression_is_binary(struct AST* expression);
+_Bool expression_is_unary(struct AST* expression);
+_Bool state_is_in_states(struct AST_State *state,struct AST_States *states);
+_Bool check_expression(struct AST *state,struct AST_Translation_Unit *unit);
+_Bool check_transition(struct AST *state,struct AST_Translation_Unit *unit);
#endif
diff --git a/src/backend/targets/C/ast_to_c.c b/src/backend/targets/C/ast_to_c.c
index 346801c..79d6017 100644
--- a/src/backend/targets/C/ast_to_c.c
+++ b/src/backend/targets/C/ast_to_c.c
@@ -3,10 +3,118 @@
#include <ast_to_c.h>
#include <print.h>
-void ast_to_c(FILE *out,struct AST *tree)
+void ast_to_c(char *output_name,struct AST *tree)
{
- assert(tree->type==AST_TYPE_MACHINE);
- ast_machine_to_c(out,(struct AST_Machine*)tree);
+ size_t output_name_length;
+ char *hold_name;
+ FILE *hold_out;
+
+ if(output_name!=NULL)
+ {
+ output_name_length=strnlen(output_name,1000);
+
+ hold_name=calloc(output_name_length+100,1);
+ memcpy(hold_name,output_name,output_name_length);
+
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+}
+void ast_translation_unit_to_c_print_base_name(FILE *out, char *base_name)
+{
+ size_t i;
+ for(i=0;i<1000 && base_name[i]!='\0';++i)
+ fprintf(out,"%c",toupper(base_name[i]));
+}
+void ast_translation_unit_to_c_print_header_string(FILE *out,char *base_name,char *file_suffix)
+{
+ fprintf(out,"#ifndef ");
+ ast_translation_unit_to_c_print_base_name(out,base_name);
+ fprintf(out,"%s\n#define ",file_suffix);
+ ast_translation_unit_to_c_print_base_name(out,base_name);
+ fprintf(out,"%s ",file_suffix);
+ ast_translation_unit_to_c_print_base_name(out,base_name);
+ fprintf(out,"%s\n",file_suffix);
+}
+void ast_translation_unit_to_c_print_footer_string(FILE *out,char *base_name,char *file_suffix)
+{
+ fprintf(out,"\n#endif //#ifndef ");
+ 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)
+{
+ size_t i;
+ if(base_name)
+ {
+ ast_translation_unit_to_c_print_header_string(out,base_name,"_H");
+ fprintf(out,"#include<stdlib.h>\n\n");
+ }
+
+ ast_to_c_print_internal_stuff_for_header(out,translation_unit);
+
+ 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)
+{
+ size_t i;
+
+ if(base_name)
+ {
+ ast_translation_unit_to_c_print_header_string(out,base_name,"_C");
+ fprintf(out,"#include \"%s.h\"\n",base_name);
+ fprintf(out,"#include \"%s_external.h\"\n\n",base_name);
+ }
+
+ 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)
+{
+ if(base_name)
+ {
+ ast_translation_unit_to_c_print_header_string(out,base_name,"_EXTERNAL_H");
+ fprintf(out,"#include \"%s.h\"\n\n",base_name);
+ }
+
+ Map_Map_Extended(translation_unit->used_commands_map,(void (*)(void*,void*))ast_command_to_c_extern_declaration,out);
+
+ if(base_name)
+ {
+ ast_translation_unit_to_c_print_footer_string(out,base_name,"_EXTERNAL_H");
+ }
}
void ast_machine_to_c(FILE *out,struct AST_Machine *machine)
{
@@ -17,7 +125,6 @@ void ast_machine_to_c(FILE *out,struct AST_Machine *machine)
ast_machine_to_c_make_header_part(out,machine);
ast_machine_to_c_make_body_part(out,machine);
-
}
void ast_machine_to_c_make_body_part(FILE *out,struct AST_Machine *machine)
{
@@ -36,8 +143,6 @@ void ast_machine_to_c_make_body_part(FILE *out,struct AST_Machine *machine)
}
void ast_machine_to_c_make_header_part(FILE *out,struct AST_Machine *machine)
{
- fprintf(out,"typedef struct machine_buffer_t \n{"
- "\n\tsize_t size;\n\tunsigned char buffer[];\n} machine_buffer_t;\n\n");
ast_events_to_c(out,machine);
ast_states_to_c(out,machine);
}
@@ -48,15 +153,13 @@ void ast_events_to_c(FILE *out,struct AST_Machine *machine)
assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);
fprintf(out,"enum ");
- ast_event_name_to_c(out,machine);
+ ast_machine_enum_tag(out,machine);
fprintf(out,"\n{\n");
for(i=0;i<machine->events->number_of_events;++i)
{
fprintf(out,"\t");
- ast_token_to_c(out,machine->id);
- fprintf(out,"_EVENT_");
- ast_token_to_c(out,machine->events->events[i]->name);
+ ast_event_to_c_enum(out,machine,machine->events->events[i]);
fprintf(out,",\n");
}
fprintf(out,"};\n");
@@ -75,19 +178,31 @@ 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;
- ast_state_to_c_signature(out,machine,vector->state);
- fprintf(out,"\n{\n\n\tswitch(event)\n\t{\n");
- for(i=0;i<vector->number_of_transitions;++i)
+ //fprintf(out,"\tmachine_buffer_t *hold_buffer;\n\thold_buffer=input;\n\n");
+
+ if(vector->number_of_transitions>0)
{
- fprintf(out,"\t\tcase ");
- ast_token_to_c(out,vector->transitions[i]->event->name);
- fprintf(out,":\n");
- ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline);
- fprintf(out,"\n\t\t\tbreak;\n");
+ fprintf(out,"\tswitch(event)\n\t{\n");
+ for(i=0;i<vector->number_of_transitions;++i)
+ {
+ fprintf(out,"\t\tcase ");
+ ast_event_to_c_enum(out,machine,vector->transitions[i]->event);
+
+ fprintf(out,":\n");
+ ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline);
+ fprintf(out,"\t\t\tmachine_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,"\t}\n");
}
+ fprintf(out,"\tdelete_machine_buffer(input);\n");
}
-void ast_event_name_to_c(FILE *out,struct AST_Machine *machine)
+/*prints the enum tag for the given machine*/
+void ast_machine_enum_tag(FILE *out,struct AST_Machine *machine)
{
fprintf(out,"MACHINE_");
ast_token_to_c(out,machine->id);
@@ -95,13 +210,9 @@ void ast_event_name_to_c(FILE *out,struct AST_Machine *machine)
}
void ast_state_to_c_signature(FILE *out,struct AST_Machine *machine,struct AST_State *state)
{
- fprintf(out,"void machine_");
- ast_token_to_c(out,machine->id);
- fprintf(out,"_state_");
- ast_token_to_c(out,state->name);
- fprintf(out,"(enum ");
- ast_event_name_to_c(out,machine);
- fprintf(out," event)\n");
+ fprintf(out,"void ");
+ ast_state_to_c_function_name(out,machine,state);
+ fprintf(out,"(int event,machine_buffer_t *input)");
}
void ast_token_to_c(FILE *out,struct token *token)
{
@@ -116,18 +227,16 @@ void ast_pipeline_to_c(FILE *out,size_t indentation,struct AST_Pipeline *pipelin
{
size_t i;
- ast_to_c_print_tabs(out,indentation);
- fprintf(out,"machine_buffer_t *hold_buffer;\n");
+ if(pipeline==NULL) return;
for(i=0;i<pipeline->size;++i)
{
ast_to_c_print_tabs(out,indentation);
- fprintf(out,"hold_buffer=");
- ast_command_to_c(out,pipeline->pipeline[i],"hold_buffer");
+ fprintf(out,"input=");
+ ast_command_to_c(out,pipeline->pipeline[i],"input");
fprintf(out,";\n");
}
- ast_to_c_print_tabs(out,indentation);
- fprintf(out,"delete_machine_buffer(hold_buffer);\n");
+ //ast_to_c_print_tabs(out,indentation);
}
void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer)
{
@@ -140,11 +249,11 @@ void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer)
fprintf(out,",%s)",hold_buffer);
}
-void ast_command_to_c_signature(FILE *out,struct AST_Command *command)
+void ast_command_to_c_extern_declaration(struct AST_Command *command,FILE *out)
{
- fprintf(out,"machine_buffer_t* ");
+ fprintf(out,"extern machine_buffer_t* ");
ast_token_to_c(out,command->function_name);
- fprintf(out,"machine_buffer_t *arguments,machine_buffer_t *input)");
+ fprintf(out,"(machine_buffer_t *arguments,machine_buffer_t *input);\n");
}
void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs)
{
@@ -152,4 +261,113 @@ void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs)
for(i=0;i<number_of_tabs;++i)
fprintf(out,"\t");
}
+void ast_machines_to_c_array(FILE *out,struct AST_Translation_Unit *translation_unit)
+{
+ size_t i;
+
+ fprintf(out,"void (*machine_states[])(int,machine_buffer_t*)={");
+ for(i=0;i<translation_unit->number_of_machines;++i)
+ {
+ ast_state_to_c_function_name(out,translation_unit->machines[i],translation_unit->machines[i]->starting_state);
+ fprintf(out,",");
+ }
+ fprintf(out,"};\n");
+}
+void ast_machines_to_c_enum(FILE *out,struct AST_Translation_Unit *translation_unit)
+{
+ size_t i;
+ fprintf(out,"enum MACHINES_ENUM\n{\n");
+ for(i=0;i<translation_unit->number_of_machines;++i)
+ {
+ fprintf(out,"\t");
+ ast_token_to_c(out,translation_unit->machines[i]->id);
+ fprintf(out,",\n");
+ }
+
+ fprintf(out,"\tMACHINES_ENUM_END\n};\n");
+}
+void ast_state_to_c_function_name(FILE *out,struct AST_Machine *machine,struct AST_State *state)
+{
+ fprintf(out,"machine_");
+ ast_token_to_c(out,machine->id);
+ fprintf(out,"_state_");
+ ast_token_to_c(out,state->name);
+}
+void ast_event_to_c_enum(FILE *out,struct AST_Machine *machine,struct AST_Event *event)
+{
+ ast_token_to_c(out,machine->id);
+ 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)
+{
+ 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");
+
+
+ ast_to_c_print_comment(out, "\tuse this function to pass an event to a machine\n"
+ "\tthe input buffer is passed to the first executed function if any\n"
+ "\tany remaining buffer after the pipeline has finished is passed\n"
+ "\tto the delete_machine_buffer function\n"
+ "\tinput can be NULL"
+
+ );
+ fprintf(out,"void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input);\n\n");
+
+
+
+
+ ast_to_c_print_comment(out, "\tthis function creates a buffer structure in the heap\n"
+ "\tit COPIES the contents of content \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)
+{
+
+ 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);"
+ "\n\t}"
+ "\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)
+{
+ fprintf(out,"/*\n");
+ fprintf(out,"%s\n",comment);
+ fprintf(out,"*/\n");
+}
#endif
diff --git a/src/backend/targets/C/ast_to_c.h b/src/backend/targets/C/ast_to_c.h
index 8c86687..6e4006f 100644
--- a/src/backend/targets/C/ast_to_c.h
+++ b/src/backend/targets/C/ast_to_c.h
@@ -4,25 +4,53 @@
#include <parser.h>
#include <backend.h>
#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
struct State_And_Transitions;
-void ast_to_c(FILE *out,struct AST *tree);
+void ast_to_c(char *output_name,struct AST *tree);
+
+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_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(FILE *out,struct AST_Translation_Unit *translation_unit);
void ast_machine_to_c(FILE *out,struct AST_Machine *machine);
void ast_machine_to_c_make_header_part(FILE *out,struct AST_Machine *machine);
void ast_machine_to_c_make_body_part(FILE *out,struct AST_Machine *machine);
+
void ast_events_to_c(FILE *out,struct AST_Machine *machine);
void ast_states_to_c(FILE *out,struct AST_Machine *machine);
-void ast_pipeline_to_c(FILE *out,size_t indentation,struct AST_Pipeline *pipeline);
void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer);
-void ast_command_to_c_signature(FILE *out,struct AST_Command *command);
+
+/*note the ordering*/
+void ast_command_to_c_extern_declaration(struct AST_Command *command,FILE *out);
+
+void ast_pipeline_to_c(FILE *out,size_t indentation,struct AST_Pipeline *pipeline);
void ast_transitions_of_state_to_c(FILE *out,struct AST_Machine *machine,struct State_And_Transitions *vector);
void ast_token_to_c(FILE *out,struct token *token);
-void ast_event_name_to_c(FILE *out,struct AST_Machine *machine);
+void ast_machine_enum_tag(FILE *out,struct AST_Machine *machine);
void ast_state_to_c_signature(FILE *out,struct AST_Machine *machine,struct AST_State *state);
+void ast_state_to_c_function_name(FILE *out,struct AST_Machine *machine,struct AST_State *state);
+void ast_machines_to_c_array(FILE *out,struct AST_Translation_Unit *translation_unit);
+void ast_machines_to_c_enum(FILE *out,struct AST_Translation_Unit *translation_unit);
+void ast_event_to_c_enum(FILE *out,struct AST_Machine *machine,struct AST_Event *event);
+
+
+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_comment(FILE *out,char *comment);
+
+
+
/* :X */
void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs);
diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c
index 6dc348d..de8ff95 100644
--- a/src/frontend/lexer.c
+++ b/src/frontend/lexer.c
@@ -37,14 +37,26 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
return get_token(src->src+src->where_in_src-sizeof("on")+1,sizeof("on")-1,KW_ON,src->current_row,src->current_column);
if(check_and_move_if_on_word("[",sizeof("[")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("[")+1,sizeof("[")-1,KW_OPEN_SQUARE,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("(",sizeof("(")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof("(")+1,sizeof("(")-1,KW_OPEN_NORMAL,src->current_row,src->current_column);
+ if(check_and_move_if_on_word(")",sizeof(")")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof(")")+1,sizeof(")")-1,KW_CLOSE_NORMAL,src->current_row,src->current_column);
if(check_and_move_if_on_word(",",sizeof(",")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof(",")+1,sizeof(",")-1,KW_COMMA,src->current_row,src->current_column);
+ if(check_and_move_if_on_word(".",sizeof(".")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof(".")+1,sizeof(".")-1,KW_DOT,src->current_row,src->current_column);
if(check_and_move_if_on_word("]",sizeof("]")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("]")+1,sizeof("]")-1,KW_CLOSE_SQUARE,src->current_row,src->current_column);
if(check_and_move_if_on_word(";",sizeof(";")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof(";")+1,sizeof(";")-1,KW_SEMI_COLUMN,src->current_row,src->current_column);
if(check_and_move_if_on_word("|",sizeof("|")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("||",sizeof("||")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof("||")+1,sizeof("||")-1,KW_OR,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("&&",sizeof("&&")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof("&&")+1,sizeof("&&")-1,KW_AND,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("!",sizeof("!")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof("!")+1,sizeof("!")-1,KW_NOT,src->current_row,src->current_column);
if(check_and_move_if_on_word("starting",sizeof("starting")-1,src,1))
return get_token(src->src+src->where_in_src-sizeof("starting")+1,sizeof("starting")-1,KW_STARTING,src->current_row,src->current_column);
if(check_and_move_if_on_word("states",sizeof("states")-1,src,1))
@@ -157,4 +169,10 @@ void push_token_into_map(struct token *token,struct Map *map,void *thing)
{
Map_Push(map,token->data,token->size,thing);
}
+void id_token_to_upper_case(struct token *token)
+{
+ size_t i;
+ for(i=0;i<token->size;++i)
+ token->data[i]=toupper(token->data[i]);
+}
#endif
diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h
index d102540..266beea 100644
--- a/src/frontend/lexer.h
+++ b/src/frontend/lexer.h
@@ -20,6 +20,8 @@ enum Keyword
KW_EOF,
KW_OPEN_SQUARE,
KW_CLOSE_SQUARE,
+ KW_OPEN_NORMAL,
+ KW_CLOSE_NORMAL,
KW_PIPE,
KW_SEMI_COLUMN,
KW_STARTING,
@@ -29,6 +31,10 @@ enum Keyword
KW_EXECUTE,
KW_TRANSITIONS,
KW_COMMA,
+ KW_DOT,
+ KW_AND,
+ KW_OR,
+ KW_NOT,
};
struct token
{
@@ -45,6 +51,7 @@ struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size
void skip_white_space(struct Source *src);
void push_token_into_map(struct token *token,struct Map *map,void *thing);
+void id_token_to_upper_case(struct token *token);
void delete_token(struct token *token);
diff --git a/src/frontend/parser.c b/src/frontend/parser.c
index 45752e7..a260622 100644
--- a/src/frontend/parser.c
+++ b/src/frontend/parser.c
@@ -13,17 +13,25 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
{
struct Queue *machines;
struct Map *hold_command_map;
+ struct Map *hold_machines_map;
struct AST_Machine *hold_machine;
machines=calloc(1,sizeof(struct Queue));
+
hold_command_map=malloc(sizeof(struct Map));
Map_Init(hold_command_map);
+ hold_machines_map=malloc(sizeof(struct Map));
+ Map_Init(hold_machines_map);
+
translation_data->hold_command_map=hold_command_map;
+ translation_data->hold_machines_map=hold_machines_map;
while(!get_and_check(translation_data,KW_EOF))
{
hold_machine=parse_machine(translation_data);
+ /*TODO check for repeated machine ids*/
+ Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
if(hold_machine)
{
Queue_Push(machines,hold_machine);
@@ -37,7 +45,7 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
return NULL;
}
}
- return get_ast_translation_unit(machines,hold_command_map);
+ return get_ast_translation_unit(machines,hold_command_map,hold_machines_map);
}
/*
* machine: 'machine' id '[' machine-inner ']' ';'
@@ -308,6 +316,10 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
{
push_parsing_error("there are no transitions",translation_data);
return NULL;
+ }else if(has_new_errors(translation_data))
+ {
+ push_parsing_error("in transition",translation_data);
+ return NULL;
}else
{
return get_ast_transitions(transitions);
@@ -328,44 +340,39 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat
if(get_and_check(translation_data,KW_FROM))
{
- if(get_kw(translation_data)==KW_ID)
+ hold_from=parse_expression(translation_data);
+ if(hold_from!=NULL)
{
- hold_token=Queue_Pop(translation_data->tokens);
- hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_from!=NULL)
+ if(get_and_check(translation_data,KW_TO))
{
- if(get_and_check(translation_data,KW_TO))
+ if(get_kw(translation_data)==KW_ID)
{
- if(get_kw(translation_data)==KW_ID)
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_to!=NULL)
{
- hold_token=Queue_Pop(translation_data->tokens);
- hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_to!=NULL)
+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
{
- if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ if(get_kw(translation_data)==KW_ID)
{
- if(get_kw(translation_data)==KW_ID)
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_event!=NULL)
{
- hold_token=Queue_Pop(translation_data->tokens);
- hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_event!=NULL)
- {
- if(get_and_check(translation_data,KW_EXECUTE))
- if((hold_pipeline=parse_pipeline(translation_data))==NULL)
- { push_parsing_error("after execute",translation_data); return NULL; }
- /*GOAL*/
- return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
- }else { push_parsing_error("event not defined",translation_data); return NULL; }
- }else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
- }else { push_parsing_error("expected 'on event'",translation_data); return NULL; }
- }else { push_parsing_error("using undefined to state in transition",translation_data); }
- }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
- }else { push_parsing_error("expected 'to'",translation_data); return NULL; }
- }else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
- }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ if(get_and_check(translation_data,KW_EXECUTE))
+ if((hold_pipeline=parse_pipeline(translation_data))==NULL)
+ { push_parsing_error("after execute",translation_data); return NULL; }
+ /*GOAL*/
+ return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
+ }else { push_parsing_error("event not defined",translation_data); return NULL; }
+ }else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'on event'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined to state in transition",translation_data); }
+ }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'to'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
}else { return NULL; }
}
/*
@@ -402,7 +409,8 @@ struct AST_Command* parse_command(struct Translation_Data *translation_data)
if(get_kw(translation_data)==KW_STRING)
string=Queue_Pop(translation_data->tokens);
ret=get_ast_command(id,string);
- Map_Push(translation_data->hold_command_map,ret->argument->data,ret->argument->size,ret);
+ if(!Map_Check(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size))
+ Map_Push(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size,ret);
return ret;
}else
@@ -441,6 +449,7 @@ struct AST_State* get_ast_state(struct token *id)
ret=malloc(sizeof(struct AST_State));
ret->name=id;
+
/*number is assigned in get_ast_states*/
return ret;
@@ -473,7 +482,9 @@ 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);
+
ret->states[states->size]=hold_state;
hold_state->number=states->size;
}
@@ -501,6 +512,7 @@ struct AST_Events* get_ast_events(struct Queue *events)
while(events->size>0)
{
hold_event=Queue_Pop(events);
+ /*TODO check for redeclaration*/
Map_Push(ret->events_map,hold_event->name->data,hold_event->name->size,hold_event);
ret->events[events->size]=hold_event;
}
@@ -510,7 +522,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_Pipeline *pipeline)
+struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
{
struct AST_Transition *ret;
ret=malloc(sizeof(struct AST_Transition));
@@ -556,6 +568,7 @@ struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,s
ret->states=states;
ret->events=events;
ret->transitions=transitions;
+ ret->starting_state=starting_state;
return ret;
}
@@ -713,7 +726,7 @@ void delete_ast_translation_unit(struct AST_Translation_Unit *ast)
free(ast->used_commands_map);
free(ast);
}
-struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map)
+struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map)
{
struct AST_Translation_Unit *ret;
struct AST_Machine *hold_machine;
@@ -721,6 +734,7 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str
ret=malloc(sizeof(struct AST_Translation_Unit)+sizeof(struct AST_Machine *[machines->size]));
ret->type=AST_TYPE_TRANSLATION_UNIT;
ret->used_commands_map=command_map;
+ ret->machines_map=machines_map;
ret->number_of_machines=machines->size;
while(machines->size>0)
@@ -731,4 +745,201 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str
return ret;
}
+/*
+ * expression: or-expression
+ */
+struct AST* parse_expression(struct Translation_Data *translation_data)
+{
+ return parse_or_expression(translation_data);
+}
+/*
+ * or-expression: and-expression [ || and-expression ]
+ */
+struct AST* parse_or_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_left_expression;
+ struct AST *hold_right_expression;
+
+ hold_left_expression=parse_and_expression(translation_data);
+ if(hold_left_expression==NULL)
+ return NULL;
+
+ if(get_and_check(translation_data,KW_OR))
+ {
+ hold_right_expression=parse_and_expression(translation_data);
+ if(hold_right_expression==NULL)
+ {
+ push_parsing_error("expected expression in right side of ||",translation_data);
+ delete_ast(hold_left_expression);
+ return NULL;
+ }
+ return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_OR);
+ }else
+ {
+ return hold_left_expression;
+ }
+
+}
+/*
+ * and-expression: not-expression [ && not-expression ]
+ */
+struct AST* parse_and_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_left_expression;
+ struct AST *hold_right_expression;
+
+ hold_left_expression=parse_not_expression(translation_data);
+ if(hold_left_expression==NULL)
+ return NULL;
+
+ if(get_and_check(translation_data,KW_AND))
+ {
+ hold_right_expression=parse_not_expression(translation_data);
+ if(hold_right_expression==NULL)
+ {
+ push_parsing_error("expected expression in right side of &&",translation_data);
+ delete_ast(hold_left_expression);
+ return NULL;
+ }
+ return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_AND);
+ }else
+ {
+ return hold_left_expression;
+ }
+}
+/*
+ * not-expression: [!]primary-expression
+ */
+struct AST* parse_not_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_expression;
+ if(get_and_check(translation_data,KW_NOT))
+ {
+ hold_expression=parse_primary_expression(translation_data);
+ if(hold_expression!=NULL)
+ {
+ return get_ast_unary_expression(hold_expression,AST_TYPE_OP_NOT);
+ }else
+ {
+ push_parsing_error("in '!' expression",translation_data);
+ return NULL;
+ }
+ }
+ return parse_primary_expression(translation_data);
+}
+/*
+ * primary-expression: (expression) | id | id.id
+ */
+struct AST* parse_primary_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_expression;
+ struct AST_Unchecked_State *hold_id1;
+ struct AST_Unchecked_State *hold_id2;
+
+ if(get_and_check(translation_data,KW_OPEN_NORMAL))
+ {
+ hold_expression=parse_expression(translation_data);
+ if(get_and_check(translation_data,KW_CLOSE_NORMAL))
+ {
+ return hold_expression;
+ }else
+ {
+ push_parsing_error("expected ')' in expression",translation_data);
+ delete_ast(hold_expression);
+ return NULL;
+ }
+
+ }else if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id1=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
+ if(get_and_check(translation_data,KW_DOT))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id2=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
+ return get_ast_binary_expression(hold_id1,hold_id2,AST_TYPE_OP_SELECTOR);
+ }else
+ {
+ push_parsing_error("expected a state id in selector",translation_data);
+ delete_ast(hold_id1);
+ return NULL;
+ }
+ }else
+ {
+ return hold_id1;
+ }
+ }else
+ {
+ push_parsing_error("expected an expression",translation_data);
+ return NULL;
+ }
+}
+struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type)
+{
+ struct AST_Binary_Expression *ret;
+
+ ret=malloc(sizeof(struct AST_Binary_Expression));
+ ret->type=type;
+ ret->left=left;
+ ret->right=right;
+
+ return ret;
+}
+struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type)
+{
+
+ struct AST_Unary_Expression *ret;
+
+ ret=malloc(sizeof(struct AST_Unary_Expression));
+
+ ret->type=type;
+ ret->operand=operand;
+
+ return ret;
+}
+struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name)
+{
+ struct AST_Unchecked_State *ret;
+
+ ret=malloc(sizeof(struct AST_Unchecked_State));
+ ret->type=AST_TYPE_UNFINISHED_STATE;
+ ret->name=name;
+
+ return ret;
+}
+
+struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data)
+{
+ struct AST_State *ret;
+ ret=Map_Check(states->states_map,state->name->data,state->name->size);
+ delete_ast_unchecked_state(state);
+ if(ret==NULL)
+ {
+ push_parsing_error("undefined state",translation_data);
+ return NULL;
+ }else
+ {
+ return ret;
+ }
+}
+
+void delete_ast_binary_expression(struct AST_Binary_Expression *ast)
+{
+ if(ast->right)
+ delete_ast(ast->right);
+ if(ast->left)
+ delete_ast(ast->left);
+ free(ast);
+}
+void delete_ast_unary_expression(struct AST_Unary_Expression *ast)
+{
+ if(ast->operand)
+ delete_ast(ast->operand);
+ free(ast);
+}
+void delete_ast_unchecked_state(struct AST_Unchecked_State *ast)
+{
+ delete_token(ast->name);
+ free(ast);
+}
#endif
diff --git a/src/frontend/parser.h b/src/frontend/parser.h
index eaede84..74f2ed8 100644
--- a/src/frontend/parser.h
+++ b/src/frontend/parser.h
@@ -5,6 +5,9 @@
#include <assert.h>
#include <map.h>
+#define AS_BIN_EXPR_PTR(x) ((struct AST_Binary_Expression*)x)
+#define AS_UN_EXPR_PTR(x) ((struct AST_Unary_Expression*)x)
+#define AS_UNCK_EXPR_PTR(x) ((struct AST_Unchecked_State*)x)
enum AST_Type
{
AST_TYPE_TRANSLATION_UNIT,
@@ -17,6 +20,11 @@ enum AST_Type
AST_TYPE_TRANSITIONS,
AST_TYPE_COMMAND,
AST_TYPE_PIPELINE,
+ AST_TYPE_OP_AND,
+ AST_TYPE_OP_OR,
+ AST_TYPE_OP_NOT,
+ AST_TYPE_OP_SELECTOR,
+ AST_TYPE_UNFINISHED_STATE,
};
struct AST
{
@@ -48,7 +56,7 @@ struct AST_Events
struct AST_Transition
{
enum AST_Type type;
- struct AST_State *from;
+ struct AST *from;
struct AST_State *to;
struct AST_Event *event;
struct AST_Pipeline *pipeline;
@@ -75,6 +83,7 @@ struct AST_Machine
{
enum AST_Type type;
struct token *id;
+ struct AST_State *starting_state;
struct AST_States *states;
struct AST_Events *events;
struct AST_Transitions *transitions;
@@ -83,9 +92,26 @@ struct AST_Translation_Unit
{
enum AST_Type type;
struct Map *used_commands_map;
+ struct Map *machines_map;
size_t number_of_machines;
struct AST_Machine *machines[];
};
+struct AST_Binary_Expression
+{
+ enum AST_Type type;
+ struct AST *left;
+ struct AST *right;
+};
+struct AST_Unary_Expression
+{
+ enum AST_Type type;
+ struct AST *operand;
+};
+struct AST_Unchecked_State
+{
+ enum AST_Type type;
+ struct token *name;
+};
struct AST* parse_source(struct Translation_Data *translation_data);
@@ -102,18 +128,28 @@ struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data);
struct AST_Command* parse_command(struct Translation_Data *translation_data);
struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states);
+struct AST* parse_expression(struct Translation_Data *translation_data);
+struct AST* parse_or_expression(struct Translation_Data *translation_data);
+struct AST* parse_and_expression(struct Translation_Data *translation_data);
+struct AST* parse_not_expression(struct Translation_Data *translation_data);
+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_Events* get_ast_events(struct Queue *events);
-struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
+struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
struct AST_Command* get_ast_command(struct token *function_name,struct token *argument);
struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline);
struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state);
struct AST_Transitions* get_ast_transitions(struct Queue *transitions);
-struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map);
+struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map);
+
+struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type);
+struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type);
+struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name);
+struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data);
void delete_ast(struct AST* ast);
void delete_ast_event(struct AST_Event* ast);
@@ -127,6 +163,10 @@ void delete_ast_machine(struct AST_Machine* ast);
void delete_ast_transitions(struct AST_Transitions* ast);
void delete_ast_translation_unit(struct AST_Translation_Unit *ast);
+void delete_ast_binary_expression(struct AST_Binary_Expression *ast);
+void delete_ast_unary_expression(struct AST_Unary_Expression *ast);
+void delete_ast_unchecked_state(struct AST_Unchecked_State *ast);
+
void pointer_array_fill(void **array,struct Queue *q);
struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim);
diff --git a/src/main.c b/src/main.c
index 1001c51..fe3a9f4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -52,7 +52,7 @@ int main(int argc,char **argv)
print_ast(translation_unit);
}else if(options->target==OPTION_TARGET_C)
{
- ast_to_c(stdout,translation_unit);
+ ast_to_c(options->output_name,translation_unit);
}
delete_ast(translation_unit);
}
diff --git a/src/program/program.c b/src/program/program.c
index 1e7882d..2632c57 100644
--- a/src/program/program.c
+++ b/src/program/program.c
@@ -40,6 +40,7 @@ struct Options* parse_command_line(int argc,char **argv)
ret=malloc(sizeof(struct Options));
ret->target=OPTION_DEFAULT;
ret->src_name=NULL;
+ ret->output_name=NULL;
ret->is_quiet=0;
for(i=0;i<argc;++i)
@@ -55,7 +56,7 @@ struct Options* parse_command_line(int argc,char **argv)
if(++i<argc)
{
if(strnlen(argv[i],101)<100)
- ret->src_name=argv[i];
+ ret->output_name=argv[i];
else if(!ret->is_quiet)
{
fprintf(stderr,"Error: Output filename is too long");
@@ -182,4 +183,8 @@ void touch_errors(struct Translation_Data *translation_data)
assert(translation_data->hold_number_of_errors>0);
--translation_data->hold_number_of_errors;
}
+void push_error_with_token(char *error_message,struct Translation_Data *translation_data,struct token *token)
+{
+ Queue_Push(translation_data->errors,get_error(error_message,token->row,token->column));
+}
#endif
diff --git a/src/program/program.h b/src/program/program.h
index 99a02c3..1fa0db6 100644
--- a/src/program/program.h
+++ b/src/program/program.h
@@ -34,6 +34,7 @@ struct Options
enum Options_Target_Type target;
int is_quiet:1;
char *src_name;
+ char *output_name;
};
struct Error
@@ -63,6 +64,7 @@ struct Error* get_error(char *message,size_t row,size_t column);
void push_lexing_error(char *error_message,struct Source *src,struct Translation_Data *translation_data);
void push_parsing_error(char *error_message,struct Translation_Data *translation_data);
+void push_error_with_token(char *error_message,struct Translation_Data *translation_data,struct token *token);
char has_new_errors(struct Translation_Data *translation_data);
void touch_errors(struct Translation_Data *translation_data);
char get_and_check(struct Translation_Data *translation_data,enum Keyword kw);
diff --git a/tests/test2 b/tests/test2
index a5342f0..f630109 100644
--- a/tests/test2
+++ b/tests/test2
@@ -1,2 +1,21 @@
-"1"
-"12"
+machine light_bulb
+[
+ states [ light_on , light_off ];
+ events [ turn_on , turn_off , switch ];
+ starting on light_off;
+ transitions
+ [
+ from light_on to light_off on event turn_off execute kek2 | kek;
+ from light_on to light_off on event switch;
+ from light_off to light_on on event turn_on;
+ from light_off to light_on on event switch execute kek;
+
+ ];
+];
+machine temp_switch
+[
+ states [A,B];
+ events [A];
+ starting on A;
+ transitions [from A to B on event A execute kek;];
+];
diff --git a/tests/test3 b/tests/test3
index 43e47d1..426fd2a 100644
--- a/tests/test3
+++ b/tests/test3
@@ -1,21 +1,15 @@
-machine light_bulb
+machine SIREN
[
- states [ light_on , light_off ];
- events [ switch_state , turn_on , turn_off ];
-
- starting on light_off;
-
+ states [ ON , OFF ];
+ events [ ECHO , TURN_OFF , TURN_ON ];
+ starting on ON ;
transitions
[
- from light_on to light_off on event switch_state execute light_switch();
- from light_off to light_on on event switch_state execute light_switch();
+ from ON to OFF on event TURN_OFF;
+ from OFF to ON on event TURN_ON;
- from light_on to light_off on event turn_on execute light_switch();
- from light_off to light_on on event turn_off execute light_switch();
- ];
-];
+ from ON to ON on event ECHO
+ execute echo ;
+ ];
-transition light_switch()
-{
-
-}
+];
diff --git a/tests/test4 b/tests/test4
new file mode 100644
index 0000000..5130059
--- /dev/null
+++ b/tests/test4
@@ -0,0 +1,24 @@
+machine light_bulb
+[
+ states [ light_on , light_off ];
+ events [ turn_on , turn_off , switch ];
+ starting on light_off;
+ transitions
+ [
+ from light_on to light_off on event turn_off execute kek2 | kek;
+ from light_on to light_off on event switch;
+ from light_off to light_on on event turn_on;
+ from light_off to light_on on event switch execute kek;
+
+ ];
+];
+machine temp_switch
+[
+ states [A,B];
+ events [A];
+ starting on A;
+ transitions
+ [
+ from ( A && !light_on ) to B on event A execute kek;
+ ];
+];