F diff --git a/.gdb_history b/.gdb_history --- a/.gdb_history +++ b/.gdb_historynnq+ b main+ r test+ n+ record+ n+ rs+ r+ record stop+ n+ print translation_unit+ print *translation_data+ print *translation_data->errors+ n+ s+ n+ s+ r test+ print ast+ b parse_unit+ r+ r test+ s+ n+ rs+ r+ record+ r+ s+ n+ rs+ r+ s+ n+ n+ rs+ r+ n+ r+ y+ s+ n+ n+ s+ n+ n+ n+ r+ n+ r+ s+ n+ s+ n+ n+ n+ n+ n+ s+ n+ s+ n+ where+ r+ s+ n+ r+ s+ n+ s+ n+ n+ s+ print ast+ print *ast+ r+ s+ n+ s+ n+ b main+ r test+ n+ s+ s+ n+ s+ n+ n+ s+ n+ print ((struct token*)translation_data->tokens->first->data-)+ print ((struct token*)translation_data->tokens->first->data-))+ print ((struct token*)translation_data->tokens->first->data)+ print *((struct token*)translation_data->tokens->first->data)+ print ((struct token*)translation_data->tokens->first->data)->ytpe+ print ((struct token*)translation_data->tokens->first->data)->type]+ print ((struct token*)translation_data->tokens->first->data)->type+ b parse_unit+ r test+ s+ n+ r+ s+ n+ r+ s+ n+ n+ n+ n+ s+ n+ print machine_id+ print *machine_id+ n+ print (struct token*)translation_data->tokens->first->data+ print ((struct token*)translation_data->tokens->first->data)->type+ b parse_machine_inner+ r test+ n+ print states+ r+ n+ s+ n+ s+ n+ b parse_start_on+ r test+ n+ n+ print *hol+ print *hold_id+ n+ print hold_state+ print states->states_map+ print *states->states_map+ print hold_id->data+ print hold_id->data[hold_id->size]+ r+ r+ r test+ rs+ where+ print str+ b get_ast_states+ r+ n+ n+ print *state+ print *hold_state+ print *hold_state->id+ print hold_state->id->size+ s+ s+ n+ print id+ print tree+ print tree->ID+ n+ n+ s+ n+ print tree->ID+ b get_ast_states+ r+ r test+ n+ s+ print id+ print size+ print (char*)str+ print *(char*)str+ r+ n+ s+ print id+ print *(char*)str+ r+ n+ q+ r test+ print *ast+ print ast+ where+ b delete_ast_pipeline+ r+ n+ n+ print ast->pipeline+ print ast->pipeline[i]+ print *ast+ print ast->pipeline[0]+ print ast->pipeline[1]+ print ast->pipeline[2]+ print ast->pipeline[3]+ print ast->pipeline[4]+ print ast->pipeline[5]+ b get_ast_pipeline+ r+ n+ b parse_pipeline+ r+ where+ b parse_unit+ r test+ s+ n+ r+ s+ n+ r+ s+ n+ s+ n+ print starting_state+ print *starting_state+ print *starting_state->id+ n+ n+ print ( (struct token *)translation_data->tokens->first->data)->id+ print ( (struct token *)translation_data->tokens->first->data)->type+ print *translation_data+ print *translation_data->errors+ b 124+ r+ co+ c+ s+ n+ n+ n+ n+ print ( (struct token *)translation_data->tokens->first->data)->type+ rs+ r+ c+ s+ n+ s+ qF diff --git a/lexer.c b/lexer.c --- a/lexer.c +++ b/lexer.c{if(check_and_move_if_on_word("machine",sizeof("machine")-1,src,1))return get_token(src->src+src->where_in_src-sizeof("machine")+1,sizeof("machine")-1,KW_MACHINE,src->current_row,src->current_column);- if(check_and_move_if_on_word("state",sizeof("state")-1,src,1))- return get_token(src->src+src->where_in_src-sizeof("state")+1,sizeof("state")-1,KW_STATE,src->current_row,src->current_column);if(check_and_move_if_on_word("from",sizeof("from")-1,src,1))return get_token(src->src+src->where_in_src-sizeof("from")+1,sizeof("from")-1,KW_FROM,src->current_row,src->current_column);if(check_and_move_if_on_word("to",sizeof("to")-1,src,1))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_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_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_PIPE,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))+ return get_token(src->src+src->where_in_src-sizeof("states")+1,sizeof("states")-1,KW_STATES,src->current_row,src->current_column);+ if(check_and_move_if_on_word("events",sizeof("events")-1,src,1))+ return get_token(src->src+src->where_in_src-sizeof("events")+1,sizeof("events")-1,KW_EVENTS,src->current_row,src->current_column);+ if(check_and_move_if_on_word("execute",sizeof("execute")-1,src,1))+ return get_token(src->src+src->where_in_src-sizeof("execute")+1,sizeof("execute")-1,KW_EXECUTE,src->current_row,src->current_column);+ if(check_and_move_if_on_word("event",sizeof("event")-1,src,1))+ return get_token(src->src+src->where_in_src-sizeof("event")+1,sizeof("event")-1,KW_EVENT,src->current_row,src->current_column);+ if(check_and_move_if_on_word("transitions",sizeof("transitions")-1,src,1))+ return get_token(src->src+src->where_in_src-sizeof("transitions")+1,sizeof("transitions")-1,KW_TRANSITIONS,src->current_row,src->current_column);else if( (needs_space_after && isspace(src->src[src->where_in_src+i])) || !needs_space_after ){src->where_in_src+=i;+ src->current_column+=i;return 1;}elsevoid skip_white_space(struct Source *src){while(src->where_in_src<src->src_size && isspace(src->src[src->where_in_src]))+ {+ if(src->src[src->where_in_src]=='\n')+ {+ ++src->current_row;+ src->current_column=0;+ }++src->where_in_src;+ }+ }++ void push_token_into_map(struct token *token,struct Map *map,void *thing)+ {+ Map_Push(map,token->data,token->size,thing);}#endifF diff --git a/lexer.h b/lexer.h --- a/lexer.h +++ b/lexer.h#include <ctype.h> //isspace#include <program.h>#include <queue.h>+ #include <map.h>struct Translation_Data;struct Source;enum Keyword{KW_MACHINE,- KW_STATE,KW_FROM,KW_TO,KW_ON,KW_PIPE,KW_SEMI_COLUMN,KW_STARTING,+ KW_STATES,+ KW_EVENTS,+ KW_EVENT,+ KW_EXECUTE,+ KW_TRANSITIONS,+ KW_COMMA,};struct token{struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column);void skip_white_space(struct Source *src);+ void push_token_into_map(struct token *token,struct Map *map,void *thing);void delete_token(struct token *token);F diff --git a/main.c b/main.c --- a/main.c +++ b/main.c- #include<stdio.h>- #include<program.h>- #include<lexer.h>- #include<string.h>- #include<print.h>+ #include <stdio.h>+ #include <program.h>+ #include <lexer.h>+ #include <string.h>+ #include <parser.h>+ #include <print.h>struct Source *source;struct Program *program;struct Translation_Data *translation_data;+ struct AST* translation_unit;- options=parse_command_line(argv);- if(options->source==NULL)+ options=parse_command_line(argc,argv);+ if(options->src_name==NULL){printf("No source file specified\n");return 0;}- source=extract_source(strdup(options->source));+ source=extract_source(strndup(options->src_name,100));translation_data=get_translation_data();-- if(options->print_tokens)+ if(options->target==OPTION_TARGET_TOKENS || options->target==OPTION_TARGET_AST){lex(translation_data->tokens,source,translation_data);if(translation_data->errors->size>0)printf("There was an error!\n");print_tokens(translation_data->tokens);return 1;- }else+ }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+ {+ translation_unit=parse_unit(translation_data);+ if(has_new_errors(translation_data))+ {+ print_errors(translation_data);+ return 1;+ }else+ {+ print_ast(translation_unit);+ delete_ast(translation_unit);+ }}+ }else+ {+ assert(!"false");}delete_source(source);F diff --git a/makefile b/makefile --- a/makefile +++ b/makefileINCLUDE_DIRS=-I .CFLAGS="-g"- main.exe : main.c lexer.o queue.o print.o program.o- gcc ${CFLAGS} main.c lexer.o queue.o print.o program.o -o main.exe ${INCLUDE_DIRS}+ main.exe : main.c lexer.o queue.o print.o program.o parser.o map.o stack.o+ gcc ${CFLAGS} main.c lexer.o queue.o print.o program.o parser.o map.o stack.o -o main.exe ${INCLUDE_DIRS}lexer.o : lexer.c lexer.hgcc ${CFLAGS} -c lexer.c -o lexer.o ${INCLUDE_DIRS}queue.o : queue.c queue.hgcc ${CFLAGS} -c print.c -o print.o ${INCLUDE_DIRS}program.o : program.c program.hgcc ${CFLAGS} -c program.c -o program.o ${INCLUDE_DIRS}-+ parser.o : parser.c parser.h+ gcc ${CFLAGS} -c parser.c -o parser.o ${INCLUDE_DIRS}+ map.o : map.c map.h+ gcc ${CFLAGS} -c map.c -o map.o ${INCLUDE_DIRS}+ stack.o : stack.c stack.h+ gcc ${CFLAGS} -c stack.c -o stack.o ${INCLUDE_DIRS}clear:- rm -rf lexer.o main.exe queue.o print.o program.o+ rm -rf lexer.o main.exe queue.o print.o program.o parser.o map.o stack.oF diff --git a/map.c b/map.c new file mode 100644 --- /dev/null +++ b/map.c+ #ifndef GMAP_C+ #define GMAP_C GMAP_C+ #include <map.h>++++ /*+ * ID and residue and all of delta is assigned to NULL+ * */+ void Map_Init(Map *tree)+ {+ tree->is_final=0;+ for(int i=0;i<256;++i)tree->delta[i] = NULL;+ tree->ID = NULL;+ }++ void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node)+ {+ for(+ *where=0,*final_node=tree;+ *where<size && final_node[0]->delta[((unsigned char*)str)[ where[0] ]]!=NULL;+ ++where[0]+ )+ {+ (*final_node) = (*final_node)->delta[((unsigned char*)str)[*where]];+ }+ }++++ /*+ * tree must not be null+ * */+ void Map_Push(Map *tree,void *str,size_t size,void *id)+ {+ size_t temp;+ Map_Scour(tree,str,size,&temp,&tree);++ if(temp == size)+ {+ assert(tree->ID==NULL);+ tree->ID=id;+ tree->is_final=1;+ return;+ }+ for(temp;temp<size;++temp)+ {+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));+ /*+ Map_Init(+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))+ );+ */+ }++ tree->ID=id;+ tree->is_final=1;++ }+++ /*+ * scours the tree and returns the id of the node that recognises the str+ * returns NULL if the string is not recognised+ * */+ void* Map_Check(Map *tree, void *str,size_t size)+ {+ size_t temp;+ Map_Scour(tree,str,size,&temp,&tree);++ if(temp<size)+ {+ return NULL;+ }else+ {+ return tree->ID; //this has been set to be the last reached node+ }+ }++ void Map_Remove(Map *tree, void *str,size_t size)+ {+ Stack stk;+ Stack_Init(&stk);+ size_t where;+ char what_to_null=((char*)str)[0];++ Stack_Push(&stk,tree);++ for(where=0;where<size-1 && tree->delta[((unsigned char*)str)[where]]!=NULL;++where)+ {+ tree = tree->delta[((unsigned char*)str)[where]];+ if(tree->is_final==1)+ {+ while(stk.size>0)Stack_Pop(&stk);+ what_to_null=((char*)str)[where+1];+ }+ Stack_Push(&stk,tree);+ }+ if(tree->delta[((unsigned char*)str)[where]] == NULL)return;+ free(tree->delta[((unsigned char*)str)[where]]);+ while(stk.size>1)free(Stack_Pop(&stk));+ tree=(Map*)Stack_Pop(&stk);+ tree->delta[(unsigned char)what_to_null]=NULL;++ }+ /*This function especially requires that the map has no loops*/+ void Map_Map(Map *tree,void (*map)(void*))+ {+ if(tree->is_final==1)map(tree->ID);+ for(int i=0;i<256;++i)+ {+ if(tree->delta[i]!=NULL)+ {+ Map_Map(tree->delta[i],map);+ }+ }+ }++ /*first argument of map is the node id , the second is pass_data*/+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data)+ {+ if(tree->is_final==1)map(tree->ID,pass_data);+ for(int i=0;i<256;++i)+ {+ if(tree->delta[i]!=NULL)+ {+ Map_Map_Extended(tree->delta[i],map,pass_data);+ }+ }+ }+++ /*this does not destroy(free) any memory pointed to by a node in the Map. This does not free() the root (Map *tree) */+ /*This function especially does not require that the map has no loop ( for example after grepification )*/+ void Map_Destroy(Map *tree)+ {+ Stack path;+ Stack nodes;+ Map *current_node;+ unsigned int i;+++ Stack_Init(&path);+ Stack_Init(&nodes);++ Stack_Push(&path,tree);+ Stack_Push(&nodes,tree);++ /*+ using DFS we fill up the nodes stack with all the used+ (accessible) nodes.+ */+ while(path.size>0)+ {+ current_node=Stack_Pop(&path);+ current_node->ID=&(current_node->ID);/*mark the node*/+ for(i=0;i<256;++i)+ {+ if(current_node->delta[i]!=NULL && current_node->delta[i]->ID != &(current_node->delta[i]->ID) )+ {+ Stack_Push(&path,current_node->delta[i]);+++ /*we mark the unmarked child of the current_node*/+ current_node->delta[i]->ID=&(current_node->delta[i]->ID);+ /*every node in nodes continues to be marked*/+ Stack_Push(&nodes,current_node->delta[i]);+ }+ }++ }+ /*+ There should not be any duplicates in here+ */+ while(nodes.size>1)+ {+ current_node=Stack_Pop(&nodes);+ /*Again the things that ID points to is not freed ( this structure is used to map the structure of data )+ deletion of it is up to you.+ */+ free(current_node);+ }+ /*this is where the root is at- we don't delete it , but we must free the last stack node*/+ Stack_Pop(&nodes);+++ }++ /*requres that cpy has no loops*/+ Map* Map_Copy(Map *cpy)+ {+ short i;+ Map *ret;++ if(cpy==NULL)+ {+ return NULL;+ }++ ret=malloc(sizeof(Map));+ ret->is_final=cpy->is_final;+ ret->ID=cpy->ID;++ for(i=0;i<256;++i)+ {+ ret->delta[i]=Map_Copy(cpy->delta[i]);+ }+ return ret;+ }++ struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size)+ {+ size_t temp;+ Map_Scour(tree,str,size,&temp,&tree);++ if(temp<size)+ {+ return NULL;+ }else+ {+ return tree;+ }+ }++ struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id)+ {+ size_t temp;+ Map_Scour(tree,str,size,&temp,&tree);++ if(temp == size)+ {+ if(tree->ID!=NULL)tree->ID=id;+ tree->is_final=1;+ return tree;+ }++ for(temp;temp<size;++temp)+ {+ Map_Init(+ tree=+ tree->delta[((unsigned char*)str)[temp]]=+ malloc(sizeof(Map))+ );+ }++ tree->ID=id;+ tree->is_final=1;+ return tree;+ }++ void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id)+ {+ size_t temp;+ Map_Scour(tree,str,size,&temp,&tree);++ if(temp == size)+ {+ if(!tree->is_final)+ {+ tree->ID=id;+ tree->is_final=1;+ }+ return tree->ID;+ }+ for(temp;temp<size;++temp)+ {+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));+ /*+ Map_Init(+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))+ );+ */+ }++ tree->ID=id;+ tree->is_final=1;+ return NULL;+ }+ /*requires that the map has no loops. does not free the root node*/+ /*TODO*/+ void Map_Delete_Map(struct Map *tree)+ {++ }+ #endif //#ifndef GMAPF diff --git a/map.h b/map.h new file mode 100644 --- /dev/null +++ b/map.h+ #ifndef GMAP_H+ #define GMAP_H GMAP_H+ #include <stdlib.h>+ #include <stdio.h>+ #include <stack.h>+ #include <queue.h>+ #include <assert.h>++ typedef struct Map Map;++++ /*+ * A looples automata with things attached to the nodes+ * */+ struct Map+ {+ char is_final;+ Map *delta[256];+ /*ID cannot point to itself ( this is used in the deletion of the map ) */+ void *ID;+ };++ void Map_Init(Map *tree);+ void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node);+ void Map_Push(Map *tree,void *str,size_t size,void *id);+ void* Map_Check(Map *tree, void *str,size_t size);+ struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size);+ void Map_Remove(Map *tree, void *str,size_t size);+ void Map_Map(Map *tree,void (*map)(void*));+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);++ void Map_Destroy(Map *tree);+ void Map_Delete_Map(struct Map *tree);+ struct Condensed_Map* Map_Condense(Map* tree);++ struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id);+ /*returns NULL if id is not taken , returns pointer to taken id otherwise*/+ void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id);++ #endifF diff --git a/parser.c b/parser.c new file mode 100644 --- /dev/null +++ b/parser.c+ #ifndef PARSER_C+ #define PARSER_C PARSER_C+ #include <parser.h>++ /*+ * parse-unit: machine+ *+ */+ struct AST* parse_unit(struct Translation_Data *translation_data)+ {+ return (struct AST*)parse_machine(translation_data);+ }+ /*+ * machine: 'machine' id '[' machine-inner ']' ';'+ *+ */+ struct AST_Machine* parse_machine(struct Translation_Data *translation_data)+ {+ struct AST_Machine *ret;+ struct token *hold_id;+ if(get_and_check(translation_data,KW_MACHINE))+ {+ if(get_kw(translation_data)==KW_ID)+ {+ hold_id=Queue_Pop(translation_data->tokens);+ if(get_and_check(translation_data,KW_OPEN_SQUARE))+ {+ ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data);+ if(has_new_errors(translation_data))+ {+ delete_ast_machine(ret);+ touch_errors(translation_data);++ return NULL;+ }+ if(get_and_check(translation_data,KW_CLOSE_SQUARE))+ {+ if(get_and_check(translation_data,KW_SEMI_COLUMN))+ return ret;+ else+ {+ push_parsing_error("';' expected after machine definition",translation_data);+ delete_ast_machine(ret);+ return NULL;+ }+ }else+ {+ push_parsing_error("closing ']' expected",translation_data);+ delete_ast_machine(ret);+ return NULL;+ }+ }else+ {+ push_parsing_error("opening '[' expected",translation_data);+ return NULL;+ }+ }else+ {+ push_parsing_error("expected a name for the machine",translation_data);+ return NULL;+ }+ }else+ {+ push_parsing_error("'machine' expected",translation_data);+ return NULL;+ }+ }+ /*+ * machine-inner : 'states' '[' states-inner ']' ';'+ * 'events' '[' events-inner ']' ';'+ * 'transitions' '[' transitions-inner ']' ';'+ * 'starting' start-on-inner ';'+ */+ struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data)+ {+ struct AST_States *states=NULL;+ struct AST_Events *events=NULL;+ struct AST_Transitions *transitions=NULL;+ struct AST_State *starting_state=NULL;+ unsigned char i;+ for(i=0;i<4;++i)+ switch(get_kw(translation_data))+ {+ case KW_STATES:+ if(states)+ {+ push_parsing_error("defining two sets of states",translation_data);+ goto error_cleanup;+ }else+ {+ chomp(translation_data);+ if(get_and_check(translation_data,KW_OPEN_SQUARE))+ {+ states=parse_states_inner(translation_data);+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)+ || !get_and_check(translation_data,KW_SEMI_COLUMN))+ {+ push_parsing_error("expected ']' and ';' at "+ "end of states definition",translation_data);+ goto error_cleanup;+ }++ }else+ {+ push_parsing_error("expected '[' ",translation_data);+ goto error_cleanup;+ }+ }+ break;+ case KW_TRANSITIONS:+ if(states==NULL && events==NULL)+ {+ push_parsing_error("defining transitions before states and events",translation_data);+ goto error_cleanup;+ }else if(transitions)+ {+ push_parsing_error("defining two sets of transitions",translation_data);+ goto error_cleanup;+ }else+ {+ chomp(translation_data);+ if(get_and_check(translation_data,KW_OPEN_SQUARE))+ {+ transitions=parse_transitions_inner(translation_data,states,events);+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)+ || !get_and_check(translation_data,KW_SEMI_COLUMN))+ {+ push_parsing_error("expected ']' and ';' at "+ "end of transitions definition",translation_data);+ goto error_cleanup;+ }+ }else+ {+ push_parsing_error("expected '[' ",translation_data);+ goto error_cleanup;+ }+ }+ break;+ case KW_EVENTS:+ if(events)+ {+ push_parsing_error("defining two sets of transitions",translation_data);+ goto error_cleanup;+ }else+ {+ chomp(translation_data);+ if(get_and_check(translation_data,KW_OPEN_SQUARE))+ {+ events=parse_events_inner(translation_data);+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)+ || !get_and_check(translation_data,KW_SEMI_COLUMN))+ {+ push_parsing_error("expected ']' and ';' at "+ "end of events definition",translation_data);+ goto error_cleanup;+ }+ }else+ {+ push_parsing_error("expected '[' ",translation_data);+ goto error_cleanup;+ }+ }+ break;+ case KW_STARTING:+ chomp(translation_data);+ if(!starting_state)+ {+ if(states)+ {+ starting_state=parse_start_on(translation_data,states);+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))+ {+ push_parsing_error("expected ';' at end "+ "of starting state declaration",translation_data);+ goto error_cleanup;+ }+ }else+ {+ push_parsing_error("states need to be defined"+ " before defining a starting one",translation_data);+ goto error_cleanup;+ }+ }else+ {+ push_parsing_error("starting state is defined",translation_data);+ goto error_cleanup;+ }+ break;+ default:+ push_parsing_error("expected states transitions or events",translation_data);+ goto error_cleanup;++ }++ return get_ast_machine(machine_id,states,events,transitions,starting_state);++ error_cleanup:+ push_parsing_error("in machine",translation_data);+ if(states)delete_ast_states(states);+ if(events)delete_ast_events(events);+ if(transitions)delete_ast_transitions(transitions);+ return NULL;+ }+ /*+ * states-inner: state (, state)*+ *+ */+ struct AST_States* parse_states_inner(struct Translation_Data *translation_data)+ {+ struct Queue *ids;+ struct AST_State *hold_state;++ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA);+ if(ids->size==0)+ {+ push_parsing_error("there needs to be atleast one state",translation_data);+ free(ids);+ return NULL;+ }else+ {++ return get_ast_states(ids);+ }+ }+ /*+ * state : id+ *+ */+ struct AST_State* parse_state(struct Translation_Data *translation_data)+ {+ if(get_kw(translation_data)==KW_ID)+ return get_ast_state(Queue_Pop(translation_data->tokens));+ else+ return NULL;+ }+ /*+ * events-inner: id (, id)*+ *+ */+ struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)+ {+ struct Queue *ids;+ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA);+ if(ids->size==0)+ {+ push_parsing_error("there needs to be atleast one event",translation_data);+ return NULL;+ }else+ {+ return get_ast_events(ids);+ }+ }+ struct AST_Event* parse_event(struct Translation_Data *translation_data)+ {+ if(get_kw(translation_data)==KW_ID)+ return get_ast_event(Queue_Pop(translation_data->tokens));+ else+ return NULL;+ }+ /*+ * transitions-inner: ( transition ;)*+ */+ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)+ {+ struct Queue *transitions;+ struct AST_Transition *hold_transition;++ transitions=malloc(sizeof(struct Queue));+ Queue_Init(transitions);++ while((hold_transition=parse_transition(translation_data,states,events))!=NULL)+ {+ Queue_Push(transitions,hold_transition);+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))+ break;+ }++ if(transitions->size==0)+ {+ push_parsing_error("there are no transitions",translation_data);+ return NULL;+ }else+ {+ return get_ast_transitions(transitions);+ }+ }+ /*+ * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ]+ *+ */+ struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)+ {+ struct AST_Transition *ret;+ struct AST_State *hold_from;+ struct AST_State *hold_to;+ struct AST_Event *hold_event;+ struct AST_Pipeline *hold_pipeline=NULL;+ struct token *hold_token;++ if(get_and_check(translation_data,KW_FROM))+ {+ if(get_kw(translation_data)==KW_ID)+ {+ 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_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)+ {+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )+ {+ 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)+ {+ 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; }+ }else { return NULL; }+ }+ /*+ * pipeline: [ command ( | command )* ]+ *+ */+ struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data)+ {+ struct Queue *pipeline;+ pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE);+ if(pipeline->size==0)+ {+ free(pipeline);+ push_parsing_error("pipeline is empty",translation_data);+ return NULL;+ }else+ {+ return get_ast_pipeline(pipeline);+ }+ }+ /*+ * command: id [ string ]+ *+ */+ struct AST_Command* parse_command(struct Translation_Data *translation_data)+ {+ struct token *id;+ struct token *string=NULL;+ 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);+ }else+ {+ push_parsing_error("expected command id",translation_data);+ return NULL;+ }+ }+ /*+ * starting-on-inner: 'on' id ;+ */+ struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states)+ {+ struct token *hold_id;+ struct AST_State *hold_state;++ if(get_and_check(translation_data,KW_ON))+ {+ if(get_kw(translation_data)==KW_ID)+ {+ hold_id=Queue_Pop(translation_data->tokens);+ hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size);+ free(hold_id);+ if(hold_state)+ {++ return hold_state;++ }else { push_parsing_error("starting state is not defined",translation_data); return NULL; }+ }else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; }+ }else { push_parsing_error("expected 'on'",translation_data); return NULL; }+ }+ struct AST_State* get_ast_state(struct token *id)+ {+ struct AST_State *ret;++ ret=malloc(sizeof(struct AST_State));+ ret->type=AST_TYPE_STATE;+ ret->id=id;++ return ret;+ }+ struct AST_Event* get_ast_event(struct token *id)+ {+ struct AST_Event *ret;++ ret=malloc(sizeof(struct AST_Event));+ ret->type=AST_TYPE_EVENT;+ ret->id=id;++ return ret;+ }+ struct AST_States* get_ast_states(struct Queue *states)+ {+ struct AST_States *ret;+ struct AST_State *hold_state;++ /*perhaps no states error should be handled here*/+ assert(states && states->size>0);++ ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size]));+ ret->type=AST_TYPE_STATES;+ ret->number_of_states=states->size;+ ret->states_map=malloc(sizeof(struct Map));++ Map_Init(ret->states_map);++ while(states->size>0)+ {+ hold_state=Queue_Pop(states);+ Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state);+ ret->states[states->size]=hold_state;+ }++ assert(states->size==0);+ free(states);++ return ret;+ }+ struct AST_Events* get_ast_events(struct Queue *events)+ {+ struct AST_Events *ret;+ struct AST_Event *hold_event;++ /*perhaps no events error should be handled here*/+ assert(events && events->size>0);++ ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size]));+ ret->type=AST_TYPE_EVENTS;+ ret->number_of_events=events->size;+ ret->events_map=malloc(sizeof(struct Map));++ Map_Init(ret->events_map);++ while(events->size>0)+ {+ hold_event=Queue_Pop(events);+ Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event);+ ret->events[events->size]=hold_event;+ }++ assert(events->size==0);+ free(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 *ret;+ ret=malloc(sizeof(struct AST_Transition));+ ret->type=AST_TYPE_TRANSITION;+ ret->from=from;+ ret->to=to;+ ret->event=event;+ ret->pipeline=pipeline;++ return ret;+ }+ struct AST_Command* get_ast_command(struct token *function_name,struct token *argument)+ {+ struct AST_Command *ret;+ ret=malloc(sizeof(struct AST_Command));+ ret->type=AST_TYPE_COMMAND;+ ret->function_name=function_name;+ ret->argument=argument;++ return ret;+ }+ struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline)+ {+ struct AST_Pipeline *ret;++ ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size]));+ ret->type=AST_TYPE_PIPELINE;+ ret->size=pipeline->size;+ pointer_array_fill((void**)ret->pipeline,pipeline);++ assert(pipeline->size==0);+ free(pipeline);++ return ret;+ }+ 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_Machine *ret;++ ret=malloc(sizeof(struct AST_Machine));+ ret->type=AST_TYPE_MACHINE;+ ret->id=id;+ ret->states=states;+ ret->events=events;+ ret->transitions=transitions;++ return ret;+ }+ struct AST_Transitions* get_ast_transitions(struct Queue *transitions)+ {+ struct AST_Transitions *ret;+ ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size]));+ ret->type=AST_TYPE_TRANSITIONS;+ ret->size=transitions->size;++ pointer_array_fill((void**)ret->transitions,transitions);++ assert(transitions->size==0);+ free(transitions);++ return ret;+ }+ void delete_ast(struct AST* ast)+ {+ switch(ast->type)+ {+ case AST_TYPE_MACHINE:+ delete_ast_machine((struct AST_Machine*)ast);+ break;+ case AST_TYPE_STATE:+ delete_ast_state((struct AST_State*)ast);+ break;+ case AST_TYPE_STATES:+ delete_ast_states((struct AST_States*)ast);+ break;+ case AST_TYPE_EVENT:+ delete_ast_event((struct AST_Event*)ast);+ break;+ case AST_TYPE_EVENTS:+ delete_ast_events((struct AST_Events*)ast);+ break;+ case AST_TYPE_TRANSITION:+ delete_ast_transition((struct AST_Transition*)ast);+ break;+ case AST_TYPE_TRANSITIONS:+ delete_ast_transitions((struct AST_Transitions*)ast);+ break;+ case AST_TYPE_COMMAND:+ delete_ast_command((struct AST_Command*)ast);+ break;+ case AST_TYPE_PIPELINE:+ delete_ast_pipeline((struct AST_Pipeline*)ast);+ break;+ }+ }+ void delete_ast_event(struct AST_Event* ast)+ {+ if(ast==NULL)return;+ delete_token(ast->id);+ free(ast);+ }+ void delete_ast_states(struct AST_States* ast)+ {+ size_t i;+ if(ast==NULL)return;+ for(i=0;i<ast->number_of_states;++i)+ delete_ast_state(ast->states[i]);+ free(ast);+ }+ void delete_ast_events(struct AST_Events* ast)+ {+ size_t i;+ if(ast==NULL)return;+ for(i=0;i<ast->number_of_events;++i)+ delete_ast_event(ast->events[i]);+ free(ast);+ }+ void delete_ast_transition(struct AST_Transition* ast)+ {+ if(ast==NULL)return;+ if(ast->pipeline!=NULL)+ delete_ast_pipeline(ast->pipeline);+ free(ast);+ }+ void delete_ast_command(struct AST_Command* ast)+ {+ if(ast==NULL)return;+ delete_token(ast->function_name);+ if(ast->argument!=NULL)+ delete_token(ast->argument);+ free(ast);+ }+ void delete_ast_pipeline(struct AST_Pipeline* ast)+ {+ size_t i;+ if(ast==NULL)return;+ for(i=0;i<ast->size;++i)+ delete_ast_command(ast->pipeline[i]);+ free(ast);+ }+ void delete_ast_machine(struct AST_Machine* ast)+ {+ if(ast==NULL)return;+ if(ast->id!=NULL)+ delete_token(ast->id);+ if(ast->states!=NULL)+ delete_ast_states(ast->states);+ if(ast->events!=NULL)+ delete_ast_events(ast->events);+ if(ast->transitions!=NULL)+ delete_ast_transitions(ast->transitions);+ }+ void delete_ast_transitions(struct AST_Transitions* ast)+ {+ size_t i;+ if(ast==NULL)return;+ for(i=0;i<ast->size;++i)+ delete_ast_transition(ast->transitions[i]);+ free(ast);+ }+ void delete_ast_state(struct AST_State* ast)+ {+ if(ast==NULL)return;+ if(ast->id!=NULL)+ delete_token(ast->id);+ free(ast);+ }+ void pointer_array_fill(void **array,struct Queue *q)+ {+ size_t i;+ for(i=0;q->size>0;++i)+ array[i]=Queue_Pop(q);+ }++ struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim)+ {+ struct Queue *q;+ struct AST* hold_ast;++ q=malloc(sizeof(struct Queue));+ Queue_Init(q);+ while(hold_ast=parser(translation_data))+ {+ Queue_Push(q,hold_ast);+ if(!get_and_check(translation_data,delim))+ break;+ }+ return q;+ }++ #endifF diff --git a/parser.h b/parser.h new file mode 100644 --- /dev/null +++ b/parser.h+ #ifndef PARSER_H+ #define PARSER_H PARSER_H+ #include <program.h>+ #include <stddef.h>+ #include <assert.h>+ #include <map.h>++ enum AST_Type+ {+ AST_TYPE_MACHINE,+ AST_TYPE_STATE,+ AST_TYPE_STATES,+ AST_TYPE_EVENT,+ AST_TYPE_EVENTS,+ AST_TYPE_TRANSITION,+ AST_TYPE_TRANSITIONS,+ AST_TYPE_COMMAND,+ AST_TYPE_PIPELINE,+ };+ struct AST+ {+ enum AST_Type type;+ };+ struct AST_State+ {+ enum AST_Type type;+ struct token *id;+ };+ struct AST_Event+ {+ enum AST_Type type;+ struct token *id;+ };+ struct AST_States+ {+ enum AST_Type type;+ size_t number_of_states;+ struct Map *states_map;+ struct AST_State *states[];+ };+ struct AST_Events+ {+ enum AST_Type type;+ size_t number_of_events;+ struct Map *events_map;+ struct AST_Event *events[];+ };+ struct AST_Transition+ {+ enum AST_Type type;+ struct AST_State *from;+ struct AST_State *to;+ struct AST_Event *event;+ struct AST_Pipeline *pipeline;+ };+ struct AST_Command+ {+ enum AST_Type type;+ struct token *function_name;+ struct token *argument;+ };+ struct AST_Pipeline+ {+ enum AST_Type type;+ size_t size;+ struct AST_Command *pipeline[];+ };+ struct AST_Machine+ {+ enum AST_Type type;+ struct token *id;+ struct AST_States *states;+ struct AST_Events *events;+ struct AST_Transitions *transitions;+ };+ struct AST_Transitions+ {+ enum AST_Type type;+ size_t size;+ struct AST_Transition *transitions[];+ };+++ struct AST* parse_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_State* parse_state(struct Translation_Data *translation_data);+ struct AST_Events* parse_events_inner(struct Translation_Data *translation_data);+ struct AST_Event* parse_event(struct Translation_Data *translation_data);+ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events );+ struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);+ struct AST_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_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_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);+++ void delete_ast(struct AST* ast);+ void delete_ast_event(struct AST_Event* ast);+ void delete_ast_states(struct AST_States* ast);+ void delete_ast_state(struct AST_State* ast);+ void delete_ast_events(struct AST_Events* ast);+ void delete_ast_transition(struct AST_Transition* ast);+ void delete_ast_command(struct AST_Command* 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 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);++ #endifF diff --git a/print.c b/print.c --- a/print.c +++ b/print.ccase KW_MACHINE:printf("KW_MACHINE");break;- case KW_STATE:- printf("KW_STATE");- break;case KW_FROM:printf("KW_FROM");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);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/print.h b/print.h --- a/print.h +++ b/print.h#ifndef PRINT_H#define PRINT_H PRINT_H- #include<stdio.h>- #include<lexer.h>- #include<queue.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/program.c b/program.c --- a/program.c +++ b/program.cfclose(file);return ret;}- struct Options* parse_command_line(char **argv)+ struct Options* parse_command_line(int argc,char **argv){struct Options *ret;- size_t i;+ int i;++ assert(argv!=NULL && argc>0);ret=malloc(sizeof(struct Options));- ret->print_tokens=1;- ret->source=argv[1];+ ret->target=OPTION_DEFAULT;+ ret->src_name=NULL;+ ret->is_quiet=0;++ for(i=0;i<argc;++i)+ {+ if(!strncmp(argv[i],"--print-tokens",sizeof("--print-tokens")))+ ret->target=OPTION_TARGET_TOKENS;+ else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))+ ret->target=OPTION_TARGET_AST;+ else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output")))+ {+ if(++i<argc)+ {+ if(strnlen(argv[i],101)<100)+ ret->src_name=argv[i];+ else if(!ret->is_quiet)+ {+ fprintf(stderr,"Error: Output filename is too long");+ exit(1);+ }else+ {+ exit(1);+ }+ }+ }else if(strnlen(argv[i],101)<100)+ {+ ret->src_name=argv[i];+ }else if(!ret->is_quiet)+ {+ fprintf(stderr,"Error: Input filename is too long");+ exit(1);+ }else+ {+ exit(1);+ }++ }++ if(ret->target==OPTION_DEFAULT)+ ret->target=OPTION_TARGET_AST;+return ret;}struct Translation_Data* get_translation_data()struct Error *ret;ret=malloc(sizeof(struct Error));ret->message=message;- ret->row=row;- ret->column=column;+ ret->row=row+1;+ ret->column=column+1;}void push_lexing_error(char *error_message,struct Source *src,struct Translation_Data *translation_data){Queue_Push(translation_data->errors,get_error(error_message,src->current_row,src->current_column));}- void push_parsing_error(char *error_message,struct token *token ,struct Translation_Data *translation_data)+ void push_parsing_error(char *error_message,struct Translation_Data *translation_data){- Queue_Push(translation_data->errors,get_error(error_message,token->row,token->column));+ struct token *error_token;+ error_token=Queue_Pop(translation_data->tokens);+ Queue_Push(translation_data->errors,get_error(error_message,error_token->row,error_token->column));}char has_new_errors(struct Translation_Data *translation_data){free(error->message);free(error);}+ char get_and_check(struct Translation_Data *translation_data,enum Keyword kw)+ {+ if( ( (struct token *)translation_data->tokens->first->data)->type==kw)+ {+ delete_token(Queue_Pop(translation_data->tokens));+ return 1;+ }else+ {+ return 0;+ }+ }+ enum Keyword get_kw(struct Translation_Data *translation_data)+ {+ return ( (struct token*)translation_data->tokens->first->data)->type;+ }+ void chomp(struct Translation_Data *translation_data)+ {+ assert(translation_data->tokens->size>0);+ delete_token(Queue_Pop(translation_data->tokens));+ }+ void touch_errors(struct Translation_Data *translation_data)+ {+ assert(translation_data->hold_number_of_errors>0);+ --translation_data->hold_number_of_errors;+ }#endifF diff --git a/program.h b/program.h --- a/program.h +++ b/program.h#ifndef PROGRAM_H#define PROGRAM_H- #include <queue.h>- #include <lexer.h>#include <stdlib.h>#include <stdio.h>+ #include <string.h>+ #include <queue.h>+ #include <lexer.h>+ #include <assert.h>struct token;+ enum Keyword;++ enum Options_Target_Type+ {+ OPTION_TARGET_TOKENS,+ OPTION_TARGET_AST,+ OPTION_DEFAULT,+ };struct Source{struct Options{- int print_tokens:1;- char *source;+ enum Options_Target_Type target;+ int is_quiet:1;+ char *src_name;};struct Error};struct Source* extract_source(char *src_name);- struct Options* parse_command_line(char **argv);+ struct Options* parse_command_line(int argc,char **argv);struct Translation_Data* get_translation_data();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 token *token ,struct Translation_Data *translation_data);+ void push_parsing_error(char *error_message,struct Translation_Data *translation_data);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);+ enum Keyword get_kw(struct Translation_Data *translation_data);+ void chomp(struct Translation_Data *translation_data);void delete_translation_data(struct Translation_Data *data);void delete_source(struct Source *src);F diff --git a/stack.c b/stack.c new file mode 100644 --- /dev/null +++ b/stack.c+ #ifndef GSTACK_C+ #define GSTACK_C GSTACK_C+ #include "stack.h"++++ void Stack_Init(Stack *stack)+ {+ stack->size=0;+ stack->first=NULL;+ }+ void Stack_Push(Stack *stack,void* data)+ {+ struct Stack_Node *temp_node=malloc(sizeof(struct Stack_Node));+ temp_node->data=data;+ temp_node->next=stack->first;+ stack->first=temp_node;+ ++stack->size;+ }+ void* Stack_Pop(Stack *stack)+ {+ void* return_value=NULL;+ if(stack->first!=NULL)+ {+ struct Stack_Node *temp_first=stack->first;+ return_value=stack->first->data;++ --stack->size;+ stack->first=stack->first->next;+ free(temp_first);+ }++ return return_value;+ }++ #endif//#ifndef GSTACK_C+F diff --git a/stack.h b/stack.h new file mode 100644 --- /dev/null +++ b/stack.h+ #ifndef GSTACK_H+ #define GSTACK_H GSTACK_H+ #include<stdlib.h>+ typedef struct Stack Stack;++ struct Stack_Node+ {+ struct Stack_Node *next;+ void *data;+ };+ struct Stack+ {+ struct Stack_Node *first;+ size_t size;+ };++ void Stack_Init(Stack *stack);+ void Stack_Push(Stack *stack,void* data);+ void* Stack_Pop(Stack *stack);+++ #endifF diff --git a/test b/test --- a/test +++ b/test- machine temp_switch- [- state above_treshold;- starting state below_treshold;-- from below_treshold to above_treshold- on event above_temperature "10";- from above_treshold to below_treshold- on event below_temperature "9";- on state above_treshold- on event get_temp | html_encase | http_out ;+ machine flicker+ [+ states [ light_off , light_on ];++ starting on light_on;++ events [ one_second ];+ transitions+ [+ from light_on to light_off on event one_second+ execute turn_off_light;+ from light_off to light_on on event one_second+ execute turn_on_light;+ ];];+F diff --git a/test3 b/test3 new file mode 100644 --- /dev/null +++ b/test3+ machine light_bulb+ [+ states [ light_on , light_off ];+ events [ switch_state , turn_on , turn_off ];++ starting on light_off;++ 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 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();+ ];+ ];++ transition light_switch()+ {++ }