diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/backend.c | 116 | ||||
-rw-r--r-- | src/backend/backend.h | 13 | ||||
-rw-r--r-- | src/backend/targets/C/ast_to_c.c | 288 | ||||
-rw-r--r-- | src/backend/targets/C/ast_to_c.h | 36 | ||||
-rw-r--r-- | src/frontend/lexer.c | 18 | ||||
-rw-r--r-- | src/frontend/lexer.h | 7 | ||||
-rw-r--r-- | src/frontend/parser.c | 281 | ||||
-rw-r--r-- | src/frontend/parser.h | 46 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/program/program.c | 7 | ||||
-rw-r--r-- | src/program/program.h | 2 |
11 files changed, 736 insertions, 80 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); @@ -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); |