diff options
author | Galin Simeonov <gts@volconst.com> | 2021-05-17 17:29:08 +0300 |
---|---|---|
committer | Galin Simeonov <gts@volconst.com> | 2021-07-15 18:00:15 +0300 |
commit | f768d9bdb84e846d89aac66a4f3433a44241c298 (patch) | |
tree | b7e8248bebd80c8b1f911f666260ad52b7213b84 | |
parent | 679cbe58c4e53f0163588a7731154f3afe2d25aa (diff) | |
download | MEGATRON-f768d9bdb84e846d89aac66a4f3433a44241c298.tar.gz |
parser formed
-rw-r--r-- | .gdb_history | 242 | ||||
-rw-r--r-- | lexer.c | 27 | ||||
-rw-r--r-- | lexer.h | 9 | ||||
-rw-r--r-- | main.c | 38 | ||||
-rw-r--r-- | makefile | 13 | ||||
-rw-r--r-- | map.c | 285 | ||||
-rw-r--r-- | map.h | 41 | ||||
-rw-r--r-- | parser.c | 669 | ||||
-rw-r--r-- | parser.h | 124 | ||||
-rw-r--r-- | print.c | 223 | ||||
-rw-r--r-- | print.h | 22 | ||||
-rw-r--r-- | program.c | 85 | ||||
-rw-r--r-- | program.h | 27 | ||||
-rw-r--r-- | stack.c | 37 | ||||
-rw-r--r-- | stack.h | 22 | ||||
-rw-r--r-- | test | 26 | ||||
-rw-r--r-- | test3 | 21 |
17 files changed, 1862 insertions, 49 deletions
diff --git a/.gdb_history b/.gdb_history index 6b826e1..a7d0bd7 100644 --- a/.gdb_history +++ b/.gdb_history @@ -131,3 +131,245 @@ s n n q +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 +q @@ -29,8 +29,6 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d { 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)) @@ -39,6 +37,8 @@ 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_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)) @@ -47,6 +47,16 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d 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); @@ -122,6 +132,7 @@ static char check_and_move_if_on_word(char *word,size_t word_size,struct Source 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; } else @@ -132,6 +143,18 @@ static char check_and_move_if_on_word(char *word,size_t word_size,struct Source void 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); } #endif @@ -3,6 +3,7 @@ #include <ctype.h> //isspace #include <program.h> #include <queue.h> +#include <map.h> struct Translation_Data; struct Source; @@ -10,7 +11,6 @@ struct Source; enum Keyword { KW_MACHINE, - KW_STATE, KW_FROM, KW_TO, KW_ON, @@ -23,6 +23,12 @@ enum Keyword KW_PIPE, KW_SEMI_COLUMN, KW_STARTING, + KW_STATES, + KW_EVENTS, + KW_EVENT, + KW_EXECUTE, + KW_TRANSITIONS, + KW_COMMA, }; struct token { @@ -38,6 +44,7 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d 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); @@ -1,8 +1,9 @@ -#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> @@ -12,18 +13,18 @@ int main(int argc,char **argv) 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) @@ -31,11 +32,26 @@ int main(int argc,char **argv) 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); @@ -1,7 +1,7 @@ INCLUDE_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.h gcc ${CFLAGS} -c lexer.c -o lexer.o ${INCLUDE_DIRS} queue.o : queue.c queue.h @@ -10,6 +10,11 @@ print.o : print.c print.h gcc ${CFLAGS} -c print.c -o print.o ${INCLUDE_DIRS} program.o : program.c program.h gcc ${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.o @@ -0,0 +1,285 @@ +#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 GMAP @@ -0,0 +1,41 @@ +#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); + +#endif diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..3e4e449 --- /dev/null +++ b/parser.c @@ -0,0 +1,669 @@ +#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; +} + +#endif diff --git a/parser.h b/parser.h new file mode 100644 index 0000000..ef82184 --- /dev/null +++ b/parser.h @@ -0,0 +1,124 @@ +#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); + +#endif @@ -9,9 +9,6 @@ void print_keyword_enum(enum Keyword code) case KW_MACHINE: printf("KW_MACHINE"); break; - case KW_STATE: - printf("KW_STATE"); - break; case KW_FROM: printf("KW_FROM"); break; @@ -48,6 +45,24 @@ void print_keyword_enum(enum Keyword code) 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"); } @@ -55,6 +70,7 @@ void print_keyword_enum(enum Keyword code) void print_token(struct token *token) { size_t i; + assert(token); printf("[ "); print_keyword_enum(token->type); @@ -67,11 +83,212 @@ void print_token(struct token *token) 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); + } +} #endif @@ -1,11 +1,27 @@ #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); #endif @@ -30,14 +30,56 @@ struct Source* extract_source(char *src_name) fclose(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() @@ -59,16 +101,18 @@ struct Error* get_error(char *message,size_t row,size_t column) 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) { @@ -111,4 +155,29 @@ void delete_error(struct Error *error) 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; +} #endif @@ -1,11 +1,21 @@ #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 { @@ -20,8 +30,9 @@ struct Source struct Options { - int print_tokens:1; - char *source; + enum Options_Target_Type target; + int is_quiet:1; + char *src_name; }; struct Error @@ -44,13 +55,17 @@ struct Program }; 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); @@ -0,0 +1,37 @@ +#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 + @@ -0,0 +1,22 @@ +#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); + + +#endif @@ -1,12 +1,16 @@ -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; + ]; ]; + @@ -0,0 +1,21 @@ +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() +{ + +} |