F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtinclude_directories(src/)include_directories(src/backend/)+ include_directories(src/backend/targets/)+ include_directories(src/backend/targets/print/)+ include_directories(src/backend/targets/C/)include_directories(src/frontend/)include_directories(src/misc/)include_directories(src/program/)set(SOURCES- src/program/program.h- src/program/program.c- src/misc/queue.h- src/misc/stack.h- src/misc/map.h- src/misc/queue.c- src/misc/map.c- src/misc/stack.c+ src/backend/targets/C/ast_to_c.c+ src/backend/targets/C/ast_to_c.h+ src/backend/targets/print/print.c+ src/backend/targets/print/print.h+ src/backend/backend.c+ src/backend/backend.h+ src/frontend/lexer.csrc/frontend/lexer.hsrc/frontend/parser.c- src/frontend/lexer.csrc/frontend/parser.h- src/backend/print.h- src/backend/print.csrc/main.c+ src/misc/map.c+ src/misc/map.h+ src/misc/queue.c+ src/misc/queue.h+ src/misc/stack.c+ src/misc/stack.h+ src/program/program.c+ src/program/program.h)add_executable(main ${SOURCES})F diff --git a/src/backend/backend.c b/src/backend/backend.c new file mode 100644 --- /dev/null +++ b/src/backend/backend.c+ #ifndef BACKEND_C+ #define BACKEND_C BACKEND_C+ #include <backend.h>++ /*returns an array of pointers to state_and_transition structs*/+ struct State_And_Transitions** extract_transition_table(struct AST_States *states,struct AST_Transitions *transitions)+ {+ struct State_And_Transitions **ret;+ struct Queue *qs;+ size_t i;++ ret=malloc(sizeof(struct State_And_Transitions)*states->number_of_states);++ /*calloc also initialises the queues+ *i-th queue is for transitions starting from the i-th state+ * */+ qs=calloc(sizeof(struct Queue),states->number_of_states);++ /*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]);++ /*condense the queues into the arrays*/+ for(i=0;i<states->number_of_states;++i)+ {+ ret[i]=malloc(sizeof(struct State_And_Transitions)+sizeof(struct AST_Transitions *[qs[i].size]));+ ret[i]->state=states->states[i];+ ret[i]->number_of_transitions=qs[i].size;+ pointer_array_fill((void**)ret[i]->transitions,qs+i);+ }++ free(qs);++ return ret;+ }++ #endifF diff --git a/src/backend/backend.h b/src/backend/backend.h new file mode 100644 --- /dev/null +++ b/src/backend/backend.h+ #ifndef BACKEND_H+ #define BACKEND_H BACKEND_H+ #include <parser.h>+ #include <ast_to_c.h>++ /*+ * describes a given state and the transitions coming out of it+ * I should probbably have done this in the parsing stage+ */+ struct State_And_Transitions+ {+ struct AST_State *state;+ size_t number_of_transitions;+ struct AST_Transition *transitions[];+ };+ /*returns an array of state_and_transition structs*/+ struct State_And_Transitions** extract_transition_table(struct AST_States *states,struct AST_Transitions *transitions);+ #endifF diff --git a/src/backend/print.c b/src/backend/print.c deleted file mode 100644 --- a/src/backend/print.c +++ /dev/null- #ifndef PRINT_C- #define PRINT_C PRINT_C- #include<print.h>-- void print_keyword_enum(enum Keyword code)- {- switch(code)- {- case KW_MACHINE:- printf("KW_MACHINE");- break;- case KW_FROM:- printf("KW_FROM");- break;- case KW_TO:- printf("KW_TO");- break;- case KW_ON:- printf("KW_ON");- break;- case KW_ID:- printf("KW_ID");- break;- case KW_STRING:- printf("KW_STRING");- break;- case KW_NOP:- printf("KW_NOP");- break;- case KW_EOF:- printf("KW_EOF");- break;- case KW_OPEN_SQUARE:- printf("KW_OPEN_SQUARE");- break;- case KW_CLOSE_SQUARE:- printf("KW_CLOSE_SQUARE");- break;- case KW_PIPE:- printf("KW_PIPE");- break;- case KW_SEMI_COLUMN:- printf("KW_SEMI_COLUMN");- break;- case KW_STARTING:- printf("KW_STARTING");- break;- case KW_STATES:- printf("KW_STATES");- break;- case KW_EVENTS:- printf("KW_EVENTS");- break;- case KW_EVENT:- printf("KW_EVENT");- break;- case KW_TRANSITIONS:- printf("KW__TRANSITIONS");- break;- case KW_EXECUTE:- printf("KW_EXECUTE");- break;- case KW_COMMA:- printf("KW_COMMA");- break;- default:- printf("LEXERROR");- }- }- void print_token(struct token *token)- {- size_t i;- assert(token);-- printf("[ ");- print_keyword_enum(token->type);- printf(" ");- for(i=0;i<token->size;++i)- printf("%c",token->data[i]);- printf(" ] ");-- }- void print_tokens(struct Queue *tokens)- {- struct Queue_Node *it;- assert(tokens);-- for(it=tokens->first;it!=NULL;it=it->prev)- {- print_token( (struct token*)(it->data));- printf(" ");- }- }- void print_ast_enum(enum AST_Type type)- {- switch(type)- {- case AST_TYPE_MACHINE:- printf("AST_TYPE_MACHINE");- break;- case AST_TYPE_STATE:- printf("AST_TYPE_STATE");- break;- case AST_TYPE_STATES:- printf("AST_TYPE_STATES");- break;- case AST_TYPE_EVENT:- printf("AST_TYPE_EVENT");- break;- case AST_TYPE_EVENTS:- printf("AST_TYPE_EVENTS");- break;- case AST_TYPE_TRANSITION:- printf("AST_TYPE_TRANSITION");- break;- case AST_TYPE_TRANSITIONS:- printf("AST_TYPE_TRANSITIONS");- break;- case AST_TYPE_COMMAND:- printf("AST_TYPE_COMMAND");- break;- case AST_TYPE_PIPELINE:- printf("AST_TYPE_PIPELINE");- break;- default:- printf("AST_NOP");- }-- }- void print_ast(struct AST *tree)- {- assert(tree);-- switch(tree->type)- {- case AST_TYPE_MACHINE:- print_ast_machine((struct AST_Machine*)tree);- break;- case AST_TYPE_STATE:- print_ast_state((struct AST_State*)tree);- break;- case AST_TYPE_STATES:- print_ast_states((struct AST_States*)tree);- break;- case AST_TYPE_EVENT:- print_ast_event((struct AST_Event*)tree);- break;- case AST_TYPE_EVENTS:- print_ast_events((struct AST_Events*)tree);- break;- case AST_TYPE_TRANSITION:- print_ast_transition((struct AST_Transition*)tree);- break;- case AST_TYPE_TRANSITIONS:- print_ast_transitions((struct AST_Transitions*)tree);- break;- case AST_TYPE_COMMAND:- print_ast_command((struct AST_Command*)tree);- break;- case AST_TYPE_PIPELINE:- print_ast_pipeline((struct AST_Pipeline*)tree);- break;- default:- printf("noast");- }- }- void print_ast_state(struct AST_State* tree)- {- assert(tree);-- printf("[ STATE: ");- print_ast_enum(tree->type);- printf("]");- }- void print_ast_event(struct AST_Event* tree)- {- assert(tree);-- printf("[ EVENT: ");- print_ast_enum(tree->type);- printf("]");- }- void print_ast_states(struct AST_States* tree)- {- size_t i;- assert(tree);-- printf("STATES [\n");- for(i=0;i<tree->number_of_states;++i)- {- print_ast_state(tree->states[i]);- printf(" ");- }- printf("\n ] END STATES \n");- }- void print_ast_events(struct AST_Events* tree)- {- size_t i;- assert(tree);-- printf("EVENTS [\n");- for(i=0;i<tree->number_of_events;++i)- {- print_ast_event(tree->events[i]);- printf(" ");- }- printf("\n ] END EVENTS \n");- }- void print_ast_transition(struct AST_Transition* tree)- {- assert(tree);-- printf("TRANSITION [\nFROM");- print_ast_state(tree->from);- printf(" TO ");- print_ast_state(tree->to);- printf(" COMMAND {");- if(tree->pipeline==NULL)- {- printf("NULL");- }else- {- print_ast_pipeline(tree->pipeline);- }-- }- void print_ast_command(struct AST_Command* tree)- {- assert(tree);-- printf("( command ");- print_token(tree->function_name);- if(tree->argument==NULL)- {- printf(" NOARGUMENTS ");- }else- {- printf(" \"");- print_token(tree->argument);- printf("\" ");- }- printf(")");- }- void print_ast_pipeline(struct AST_Pipeline* tree)- {- size_t i;- assert(tree);- printf("PIPELINE <");- for(i=0;i<tree->size;++i)- {- print_ast_command(tree->pipeline[i]);- printf(" | ");- }- printf("> PIPELINE_END");- }- void print_ast_machine(struct AST_Machine* tree)- {- assert(tree);- printf("MACHINE ");- print_token(tree->id);- printf(" [\n");- print_ast_states(tree->states);- print_ast_events(tree->events);- print_ast_transitions(tree->transitions);- printf("] MACHINE_END\n");- }- void print_ast_transitions(struct AST_Transitions* tree)- {- size_t i;- assert(tree);- printf("TRANSITIONS [\n");- for(i=0;i<tree->size;++i)- {- print_ast_transition(tree->transitions[i]);- printf("\n");- }- printf("] TRANSITIONS_END\n");- }- void print_error(struct Error *error)- {- assert(error);- printf("Error: %s, line %ld row %ld\n",error->message,error->row,error->column);- }- void print_errors(struct Translation_Data *translation_data)- {- struct Queue_Node *it;- assert(translation_data);-- for(it=translation_data->errors->first;it!=NULL;it=it->prev)- {- print_error(it->data);- }- }- #endifF diff --git a/src/backend/print.h b/src/backend/print.h deleted file mode 100644 --- a/src/backend/print.h +++ /dev/null- #ifndef PRINT_H- #define PRINT_H PRINT_H- #include <stdio.h>- #include <lexer.h>- #include <parser.h>- #include <queue.h>--- void print_keyword_enum(enum Keyword code);- void print_token(struct token *token);- void print_tokens(struct Queue *tokens);-- void print_ast_enum(enum AST_Type type);- void print_ast(struct AST *tree);- void print_ast_state(struct AST_State* tree);- void print_ast_event(struct AST_Event* tree);- void print_ast_states(struct AST_States* tree);- void print_ast_events(struct AST_Events* tree);- void print_ast_transition(struct AST_Transition* tree);- void print_ast_command(struct AST_Command* tree);- void print_ast_pipeline(struct AST_Pipeline* tree);- void print_ast_machine(struct AST_Machine* tree);- void print_ast_transitions(struct AST_Transitions* tree);-- void print_error(struct Error *error);- void print_errors(struct Translation_Data *translation_data);- #endifF diff --git a/src/backend/targets/C/ast_to_c.c b/src/backend/targets/C/ast_to_c.c new file mode 100644 --- /dev/null +++ b/src/backend/targets/C/ast_to_c.c+ #ifndef AST_TO_C_C+ #define AST_TO_C_C AST_TO_C_C+ #include <ast_to_c.h>+ #include <print.h>++ void ast_to_c(FILE *out,struct AST *tree)+ {+ assert(tree->type==AST_TYPE_MACHINE);+ ast_machine_to_c(out,(struct AST_Machine*)tree);+ }+ void ast_machine_to_c(FILE *out,struct AST_Machine *machine)+ {++ assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_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)+ {+ size_t i;+ struct State_And_Transitions **table;++ table=extract_transition_table(machine->states,machine->transitions);++ for(i=0;i<machine->states->number_of_states;++i)+ {+ ast_state_to_c_signature(out,machine,machine->states->states[i]);+ fprintf(out,"\n{\n");+ ast_transitions_of_state_to_c(out,machine,table[i]);+ fprintf(out,"\n}\n");+ }+ }+ 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);+ }+ void ast_events_to_c(FILE *out,struct AST_Machine *machine)+ {+ size_t i;++ assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);++ fprintf(out,"enum ");+ ast_event_name_to_c(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);+ fprintf(out,",\n");+ }+ fprintf(out,"};\n");+ }+ void ast_states_to_c(FILE *out,struct AST_Machine *machine)+ {+ size_t i;+ assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);+ for(i=0;i<machine->states->number_of_states;++i)+ {+ fprintf(out,"extern ");+ ast_state_to_c_signature(out,machine,machine->states->states[i]);+ fprintf(out,";\n");+ }+ }+ 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,"\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");+ }++ }+ void ast_event_name_to_c(FILE *out,struct AST_Machine *machine)+ {+ fprintf(out,"MACHINE_");+ ast_token_to_c(out,machine->id);+ fprintf(out,"_EVENTS_ENUM");+ }+ 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");+ }+ void ast_token_to_c(FILE *out,struct token *token)+ {+ size_t i;++ assert(out!=NULL && token!=NULL);++ for(i=0;i<token->size;++i)+ fprintf(out,"%c",token->data[i]);+ }+ void ast_pipeline_to_c(FILE *out,size_t indentation,struct AST_Pipeline *pipeline)+ {+ size_t i;++ ast_to_c_print_tabs(out,indentation);+ fprintf(out,"machine_buffer_t *hold_buffer;\n");++ 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,";\n");+ }+ ast_to_c_print_tabs(out,indentation);+ fprintf(out,"delete_machine_buffer(hold_buffer);\n");+ }+ void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer)+ {+ ast_token_to_c(out,command->function_name);+ fprintf(out,"(");+ if(command->argument==NULL)+ fprintf(out,"NULL");+ else+ ast_token_to_c(out,command->argument);+ fprintf(out,",%s)",hold_buffer);+ }++ void ast_command_to_c_signature(FILE *out,struct AST_Command *command)+ {+ fprintf(out,"machine_buffer_t* ");+ ast_token_to_c(out,command->function_name);+ fprintf(out,"machine_buffer_t *arguments,machine_buffer_t *input)");+ }+ void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs)+ {+ size_t i;+ for(i=0;i<number_of_tabs;++i)+ fprintf(out,"\t");+ }+ #endifF diff --git a/src/backend/targets/C/ast_to_c.h b/src/backend/targets/C/ast_to_c.h new file mode 100644 --- /dev/null +++ b/src/backend/targets/C/ast_to_c.h+ #ifndef AST_TO_C_H+ #define AST_TO_C_H AST_TO_C_H+ #include <stdio.h>+ #include <parser.h>+ #include <backend.h>+ #include <ctype.h>++ struct State_And_Transitions;++ void ast_to_c(FILE *out,struct AST *tree);+ 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);++ 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_state_to_c_signature(FILE *out,struct AST_Machine *machine,struct AST_State *state);+ /* :X */+ void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs);++ #endifF diff --git a/src/backend/targets/print/print.c b/src/backend/targets/print/print.c new file mode 100644 --- /dev/null +++ b/src/backend/targets/print/print.c+ #ifndef PRINT_C+ #define PRINT_C PRINT_C+ #include<print.h>++ void print_keyword_enum(enum Keyword code)+ {+ switch(code)+ {+ case KW_MACHINE:+ printf("KW_MACHINE");+ break;+ case KW_FROM:+ printf("KW_FROM");+ break;+ case KW_TO:+ printf("KW_TO");+ break;+ case KW_ON:+ printf("KW_ON");+ break;+ case KW_ID:+ printf("KW_ID");+ break;+ case KW_STRING:+ printf("KW_STRING");+ break;+ case KW_NOP:+ printf("KW_NOP");+ break;+ case KW_EOF:+ printf("KW_EOF");+ break;+ case KW_OPEN_SQUARE:+ printf("KW_OPEN_SQUARE");+ break;+ case KW_CLOSE_SQUARE:+ printf("KW_CLOSE_SQUARE");+ break;+ case KW_PIPE:+ printf("KW_PIPE");+ break;+ case KW_SEMI_COLUMN:+ printf("KW_SEMI_COLUMN");+ break;+ case KW_STARTING:+ printf("KW_STARTING");+ break;+ case KW_STATES:+ printf("KW_STATES");+ break;+ case KW_EVENTS:+ printf("KW_EVENTS");+ break;+ case KW_EVENT:+ printf("KW_EVENT");+ break;+ case KW_TRANSITIONS:+ printf("KW__TRANSITIONS");+ break;+ case KW_EXECUTE:+ printf("KW_EXECUTE");+ break;+ case KW_COMMA:+ printf("KW_COMMA");+ break;+ default:+ printf("LEXERROR");+ }+ }+ void print_token(struct token *token)+ {+ size_t i;+ assert(token);++ printf("[ ");+ print_keyword_enum(token->type);+ printf(" ");+ for(i=0;i<token->size;++i)+ printf("%c",token->data[i]);+ printf(" ] ");++ }+ void print_tokens(struct Queue *tokens)+ {+ struct Queue_Node *it;+ assert(tokens);++ for(it=tokens->first;it!=NULL;it=it->prev)+ {+ print_token( (struct token*)(it->data));+ printf(" ");+ }+ }+ void print_ast_enum(enum AST_Type type)+ {+ switch(type)+ {+ case AST_TYPE_MACHINE:+ printf("AST_TYPE_MACHINE");+ break;+ case AST_TYPE_STATE:+ printf("AST_TYPE_STATE");+ break;+ case AST_TYPE_STATES:+ printf("AST_TYPE_STATES");+ break;+ case AST_TYPE_EVENT:+ printf("AST_TYPE_EVENT");+ break;+ case AST_TYPE_EVENTS:+ printf("AST_TYPE_EVENTS");+ break;+ case AST_TYPE_TRANSITION:+ printf("AST_TYPE_TRANSITION");+ break;+ case AST_TYPE_TRANSITIONS:+ printf("AST_TYPE_TRANSITIONS");+ break;+ case AST_TYPE_COMMAND:+ printf("AST_TYPE_COMMAND");+ break;+ case AST_TYPE_PIPELINE:+ printf("AST_TYPE_PIPELINE");+ break;+ default:+ printf("AST_NOP");+ }++ }+ void print_ast(struct AST *tree)+ {+ assert(tree);++ switch(tree->type)+ {+ case AST_TYPE_MACHINE:+ print_ast_machine((struct AST_Machine*)tree);+ break;+ case AST_TYPE_STATE:+ print_ast_state((struct AST_State*)tree);+ break;+ case AST_TYPE_STATES:+ print_ast_states((struct AST_States*)tree);+ break;+ case AST_TYPE_EVENT:+ print_ast_event((struct AST_Event*)tree);+ break;+ case AST_TYPE_EVENTS:+ print_ast_events((struct AST_Events*)tree);+ break;+ case AST_TYPE_TRANSITION:+ print_ast_transition((struct AST_Transition*)tree);+ break;+ case AST_TYPE_TRANSITIONS:+ print_ast_transitions((struct AST_Transitions*)tree);+ break;+ case AST_TYPE_COMMAND:+ print_ast_command((struct AST_Command*)tree);+ break;+ case AST_TYPE_PIPELINE:+ print_ast_pipeline((struct AST_Pipeline*)tree);+ break;+ default:+ printf("noast");+ }+ }+ void print_ast_state(struct AST_State* tree)+ {+ assert(tree);++ printf("[ STATE: ");+ print_token(tree->name);+ printf(" %ld",tree->number);+ printf("]");+ }+ void print_ast_event(struct AST_Event* tree)+ {+ assert(tree);++ printf("[ EVENT: ");+ print_token(tree->name);+ printf("]");+ }+ void print_ast_states(struct AST_States* tree)+ {+ size_t i;+ assert(tree);++ printf("STATES [\n");+ for(i=0;i<tree->number_of_states;++i)+ {+ print_ast_state(tree->states[i]);+ printf(" ");+ }+ printf("\n ] END STATES \n");+ }+ void print_ast_events(struct AST_Events* tree)+ {+ size_t i;+ assert(tree);++ printf("EVENTS [\n");+ for(i=0;i<tree->number_of_events;++i)+ {+ print_ast_event(tree->events[i]);+ printf(" ");+ }+ printf("\n ] END EVENTS \n");+ }+ void print_ast_transition(struct AST_Transition* tree)+ {+ assert(tree);++ printf("TRANSITION [\nFROM");+ print_ast_state(tree->from);+ printf(" TO ");+ print_ast_state(tree->to);+ printf(" COMMAND {");+ if(tree->pipeline==NULL)+ {+ printf("NULL");+ }else+ {+ print_ast_pipeline(tree->pipeline);+ }++ }+ void print_ast_command(struct AST_Command* tree)+ {+ assert(tree);++ printf("( command ");+ print_token(tree->function_name);+ if(tree->argument==NULL)+ {+ printf(" NOARGUMENTS ");+ }else+ {+ printf(" \"");+ print_token(tree->argument);+ printf("\" ");+ }+ printf(")");+ }+ void print_ast_pipeline(struct AST_Pipeline* tree)+ {+ size_t i;+ assert(tree);+ printf("PIPELINE <");+ for(i=0;i<tree->size;++i)+ {+ print_ast_command(tree->pipeline[i]);+ printf(" | ");+ }+ printf("> PIPELINE_END");+ }+ void print_ast_machine(struct AST_Machine* tree)+ {+ assert(tree);+ printf("MACHINE ");+ print_token(tree->id);+ printf(" [\n");+ print_ast_states(tree->states);+ print_ast_events(tree->events);+ print_ast_transitions(tree->transitions);+ printf("] MACHINE_END\n");+ }+ void print_ast_transitions(struct AST_Transitions* tree)+ {+ size_t i;+ assert(tree);+ printf("TRANSITIONS [\n");+ for(i=0;i<tree->size;++i)+ {+ print_ast_transition(tree->transitions[i]);+ printf("\n");+ }+ printf("] TRANSITIONS_END\n");+ }+ void print_error(struct Error *error)+ {+ assert(error);+ printf("Error: %s, line %ld row %ld\n",error->message,error->row,error->column);+ }+ void print_errors(struct Translation_Data *translation_data)+ {+ struct Queue_Node *it;+ assert(translation_data);++ for(it=translation_data->errors->first;it!=NULL;it=it->prev)+ {+ print_error(it->data);+ }+ }+ #endifF diff --git a/src/backend/targets/print/print.h b/src/backend/targets/print/print.h new file mode 100644 --- /dev/null +++ b/src/backend/targets/print/print.h+ #ifndef PRINT_H+ #define PRINT_H PRINT_H+ #include <stdio.h>+ #include <lexer.h>+ #include <parser.h>+ #include <queue.h>+++ void print_keyword_enum(enum Keyword code);+ void print_token(struct token *token);+ void print_tokens(struct Queue *tokens);++ void print_ast_enum(enum AST_Type type);+ void print_ast(struct AST *tree);+ void print_ast_state(struct AST_State* tree);+ void print_ast_event(struct AST_Event* tree);+ void print_ast_states(struct AST_States* tree);+ void print_ast_events(struct AST_Events* tree);+ void print_ast_transition(struct AST_Transition* tree);+ void print_ast_command(struct AST_Command* tree);+ void print_ast_pipeline(struct AST_Pipeline* tree);+ void print_ast_machine(struct AST_Machine* tree);+ void print_ast_transitions(struct AST_Transitions* tree);++ void print_error(struct Error *error);+ void print_errors(struct Translation_Data *translation_data);+ #endifF diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.h};struct token{- size_t size;enum Keyword type;+ size_t size;char *data;size_t row;size_t column;F diff --git a/src/frontend/parser.c b/src/frontend/parser.c --- a/src/frontend/parser.c +++ b/src/frontend/parser.c#define PARSER_C PARSER_C#include <parser.h>+ struct AST* parse_source(struct Translation_Data *translation_data)+ {+ return (struct AST*)parse_translation_unit(translation_data);+ }/*- * parse-unit: machine- *+ * translation-unit: (machine)**/- struct AST* parse_unit(struct Translation_Data *translation_data)+ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *translation_data){- return (struct AST*)parse_machine(translation_data);+ struct Queue *machines;+ struct Map *hold_command_map;+ struct AST_Machine *hold_machine;++ machines=calloc(1,sizeof(struct Queue));+ hold_command_map=malloc(sizeof(struct Map));+ Map_Init(hold_command_map);++ translation_data->hold_command_map=hold_command_map;++ while(!get_and_check(translation_data,KW_EOF))+ {+ hold_machine=parse_machine(translation_data);+ if(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;+ }+ }+ return get_ast_translation_unit(machines,hold_command_map);}/** machine: 'machine' id '[' machine-inner ']' ';'{struct token *id;struct token *string=NULL;+ struct AST_Command *ret;+if(get_kw(translation_data)==KW_ID){id=Queue_Pop(translation_data->tokens);if(get_kw(translation_data)==KW_STRING)string=Queue_Pop(translation_data->tokens);- return get_ast_command(id,string);+ ret=get_ast_command(id,string);+ Map_Push(translation_data->hold_command_map,ret->argument->data,ret->argument->size,ret);++ return ret;}else{push_parsing_error("expected command id",translation_data);struct AST_State *ret;ret=malloc(sizeof(struct AST_State));- ret->type=AST_TYPE_STATE;- ret->id=id;+ ret->name=id;+ /*number is assigned in get_ast_states*/return ret;}struct AST_Event *ret;ret=malloc(sizeof(struct AST_Event));- ret->type=AST_TYPE_EVENT;- ret->id=id;++ ret->name=id;return ret;}while(states->size>0){hold_state=Queue_Pop(states);- Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state);+ 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;}assert(states->size==0);while(events->size>0){hold_event=Queue_Pop(events);- Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event);+ Map_Push(ret->events_map,hold_event->name->data,hold_event->name->size,hold_event);ret->events[events->size]=hold_event;}void delete_ast_event(struct AST_Event* ast){if(ast==NULL)return;- delete_token(ast->id);+ delete_token(ast->name);free(ast);}void delete_ast_states(struct AST_States* ast)void delete_ast_state(struct AST_State* ast){if(ast==NULL)return;- if(ast->id!=NULL)- delete_token(ast->id);+ if(ast->name!=NULL)+ delete_token(ast->name);free(ast);}void pointer_array_fill(void **array,struct Queue *q)return q;}+ void delete_ast_translation_unit(struct AST_Translation_Unit *ast)+ {+ size_t i;+ Map_Map(ast->used_commands_map,(void (*)(void*))delete_ast_command);+ Map_Destroy(ast->used_commands_map);+ for(i=0;i<ast->number_of_machines;++i)+ {+ delete_ast_machine(ast->machines[i]);+ }+ 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 *ret;+ struct AST_Machine *hold_machine;++ 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->number_of_machines=machines->size;++ while(machines->size>0)+ {+ hold_machine=Queue_Pop(machines);+ ret->machines[machines->size]=hold_machine;+ }++ return ret;+ }#endifF diff --git a/src/frontend/parser.h b/src/frontend/parser.h --- a/src/frontend/parser.h +++ b/src/frontend/parser.henum AST_Type{+ AST_TYPE_TRANSLATION_UNIT,AST_TYPE_MACHINE,AST_TYPE_STATE,AST_TYPE_STATES,};struct AST_State{- enum AST_Type type;- struct token *id;+ struct token *name;+ size_t number;};struct AST_Event{- enum AST_Type type;- struct token *id;+ struct token *name;};struct AST_States{size_t size;struct AST_Command *pipeline[];};+ struct AST_Transitions+ {+ enum AST_Type type;+ size_t size;+ struct AST_Transition *transitions[];+ };struct AST_Machine{enum AST_Type type;struct AST_Events *events;struct AST_Transitions *transitions;};- struct AST_Transitions+ struct AST_Translation_Unit{enum AST_Type type;- size_t size;- struct AST_Transition *transitions[];+ struct Map *used_commands_map;+ size_t number_of_machines;+ struct AST_Machine *machines[];};- struct AST* parse_unit(struct Translation_Data *translation_data);+ struct AST* parse_source(struct Translation_Data *translation_data);+ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *translation_data);struct AST_Machine* parse_machine(struct Translation_Data *translation_data);struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data);struct AST_States* parse_states_inner(struct Translation_Data *translation_data);struct AST_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);void delete_ast(struct AST* ast);void delete_ast_pipeline(struct AST_Pipeline* ast);void delete_ast_machine(struct AST_Machine* ast);void delete_ast_transitions(struct AST_Transitions* ast);+ void delete_ast_translation_unit(struct AST_Translation_Unit *ast);void pointer_array_fill(void **array,struct Queue *q);F diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c#include <lexer.h>#include <string.h>#include <parser.h>+ #include <backend.h>#include <print.h>source=extract_source(strndup(options->src_name,100));translation_data=get_translation_data();- if(options->target==OPTION_TARGET_TOKENS || options->target==OPTION_TARGET_AST)+ if(options->target==OPTION_TARGET_TOKENS || options->target==OPTION_TARGET_AST || options->target==OPTION_TARGET_C){lex(translation_data->tokens,source,translation_data);if(translation_data->errors->size>0)}else if(options->target==OPTION_TARGET_TOKENS){print_tokens(translation_data->tokens);- }else if(options->target==OPTION_TARGET_AST) //we check because we will probably add more options+ }else if(options->target==OPTION_TARGET_AST || options->target==OPTION_TARGET_C){- translation_unit=parse_unit(translation_data);+ //we check because we will probably add more options+++ translation_unit=parse_source(translation_data);if(has_new_errors(translation_data)){print_errors(translation_data);return 1;- }else+ }+ if(options->target==OPTION_TARGET_AST){print_ast(translation_unit);- delete_ast(translation_unit);+ }else if(options->target==OPTION_TARGET_C)+ {+ ast_to_c(stdout,translation_unit);}+ delete_ast(translation_unit);}}elseF diff --git a/src/program/program.c b/src/program/program.c --- a/src/program/program.c +++ b/src/program/program.cret->target=OPTION_TARGET_TOKENS;else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))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],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output"))){if(++i<argc)}if(ret->target==OPTION_DEFAULT)- ret->target=OPTION_TARGET_AST;+ ret->target=OPTION_TARGET_C;return ret;}F diff --git a/src/program/program.h b/src/program/program.h --- a/src/program/program.h +++ b/src/program/program.h{OPTION_TARGET_TOKENS,OPTION_TARGET_AST,+ OPTION_TARGET_C,OPTION_DEFAULT,};struct Queue *errors;struct Queue *tokens;size_t hold_number_of_errors;+ struct Map *hold_command_map;};struct Program{F diff --git a/tests/output.c b/tests/output.c new file mode 100644 --- /dev/null +++ b/tests/output.c+ enum+ {+ EVENT_ONE_SECOND,+ }MACHINE_FLICKER_EVENT;++ enum+ {+ MACHINE_FLICKER,+ }MACHINES;++ extern void machine_flicker_light_off(enum MACHINE_FLICKER_EVENT event);+ extern void machine_flicker_light_on(enum MACHINE_FLICKER_EVENT event);++ extern machine_buffer_t* turn_on_light(machine_buffer_t *arguments,machine_buffer_t *input);+ extern machine_buffer_t* turn_off_light(machine_buffer_t *arguments,machine_buffer_t *input);++ void machine_flicker_push_event(enum MACHINE_FLICKER_EVENT event);++++ void (*machine_states[])()={machine_flicker_light_on};++++ void machine_flicker_push_event(enum MACHINE_FLICKER_EVENT event)+ {+ machine_states[MACHINE_FLICKER](event);+ }++ void machine_flicker_light_off(enum MACHINE_FLICKER_EVENT event)+ {+ switch(event)+ {+ case EVENT_ONE_SECOND:+ turn_on_light(get_machine_buffer(""));+ machine_states[MACHINE_FLICKER]=machine_flicker_light_on;+ break;+ }+ }+ void machine_flicker_light_on(enum MACHINE_FLICKER_EVENT event)+ {+ switch(event)+ {+ case EVENT_ONE_SECOND:+ turn_off_light(get_machine_buffer(""));+ machine_states[MACHINE_FLICKER]=machine_flicker_light_off;+ break;+ }+ }F diff --git a/tests/test b/tests/test --- a/tests/test +++ b/tests/test+machine flicker[states [ light_off , light_on ];+ events [ one_second ];starting on light_on;- events [ one_second ];transitions[from light_on to light_off on event one_second