From 255a49ba5a41b3854dbdfebdec75fb6229450507 Mon Sep 17 00:00:00 2001 From: Galin Simeonov Date: Mon, 31 May 2021 22:02:10 +0300 Subject: added cmake file --- .gitignore | 1 + CMakeLists.txt | 27 ++ lexer.c | 160 ------------ lexer.h | 54 ---- main.c | 60 ----- makefile | 20 -- map.c | 285 --------------------- map.h | 41 ---- parser.c | 669 -------------------------------------------------- parser.h | 124 ---------- print.c | 294 ---------------------- print.h | 27 -- program.c | 183 -------------- program.h | 76 ------ queue.c | 67 ----- queue.h | 23 -- src/backend/print.c | 294 ++++++++++++++++++++++ src/backend/print.h | 27 ++ src/frontend/lexer.c | 160 ++++++++++++ src/frontend/lexer.h | 54 ++++ src/frontend/parser.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/frontend/parser.h | 124 ++++++++++ src/main.c | 60 +++++ src/misc/map.c | 285 +++++++++++++++++++++ src/misc/map.h | 41 ++++ src/misc/queue.c | 67 +++++ src/misc/queue.h | 23 ++ src/misc/stack.c | 37 +++ src/misc/stack.h | 22 ++ src/program/program.c | 183 ++++++++++++++ src/program/program.h | 76 ++++++ stack.c | 37 --- stack.h | 22 -- test | 16 -- test2 | 2 - test3 | 21 -- tests/test | 16 ++ tests/test2 | 2 + tests/test3 | 21 ++ 39 files changed, 2189 insertions(+), 2181 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 lexer.c delete mode 100644 lexer.h delete mode 100644 main.c delete mode 100644 makefile delete mode 100644 map.c delete mode 100644 map.h delete mode 100644 parser.c delete mode 100644 parser.h delete mode 100644 print.c delete mode 100644 print.h delete mode 100644 program.c delete mode 100644 program.h delete mode 100644 queue.c delete mode 100644 queue.h create mode 100644 src/backend/print.c create mode 100644 src/backend/print.h create mode 100644 src/frontend/lexer.c create mode 100644 src/frontend/lexer.h create mode 100644 src/frontend/parser.c create mode 100644 src/frontend/parser.h create mode 100644 src/main.c create mode 100644 src/misc/map.c create mode 100644 src/misc/map.h create mode 100644 src/misc/queue.c create mode 100644 src/misc/queue.h create mode 100644 src/misc/stack.c create mode 100644 src/misc/stack.h create mode 100644 src/program/program.c create mode 100644 src/program/program.h delete mode 100644 stack.c delete mode 100644 stack.h delete mode 100644 test delete mode 100644 test2 delete mode 100644 test3 create mode 100644 tests/test create mode 100644 tests/test2 create mode 100644 tests/test3 diff --git a/.gitignore b/.gitignore index 4ddaac8..e260b0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ tags *.exe *.o +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..415816f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required (VERSION 3.13.4) +project (AUTOMATA) + +include_directories(src/) +include_directories(src/backend/) +include_directories(src/frontend/) +include_directories(src/misc/) +include_directories(src/program/) + +set(SOURCES + src/program/program.h + src/program/program.c + src/misc/queue.h + src/misc/stack.h + src/misc/map.h + src/misc/queue.c + src/misc/map.c + src/misc/stack.c + src/frontend/lexer.h + src/frontend/parser.c + src/frontend/lexer.c + src/frontend/parser.h + src/backend/print.h + src/backend/print.c + src/main.c + ) +add_executable(main ${SOURCES}) diff --git a/lexer.c b/lexer.c deleted file mode 100644 index 6dc348d..0000000 --- a/lexer.c +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef LEXER_C -#define LEXER_C -#include - -#define IS_ID_CHAR(x) ( (x <= 'z' && x>='a') || ( x <= 'Z' && x >= 'A' ) || x=='_') -#define IS_DIGIT(x) ( x <= '9' && x >= '0' ) -#define IS_ID_THING(x) ( IS_ID_CHAR(x) || IS_DIGIT(x)) -#define LEX_ERROR(x) {push_lexing_error(x,src,translation_data); return get_token(src->src+src->where_in_src,0,KW_NOP,src->current_row,src->current_column);} - -/* - * placeholder very slow lexer that I will probabbly not replace - */ -void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data) -{ - skip_white_space(src); - while(src->where_in_srcsrc_size) - { - Queue_Push(token_destination,lex_step(src,translation_data)); - if(has_new_errors(translation_data)) - return; - else - skip_white_space(src); - } - Queue_Push(token_destination,get_token(NULL,0,KW_EOF,src->current_row,src->current_column)); -} - - -struct token* lex_step(struct Source *src,struct Translation_Data *translation_data) -{ - 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("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("to")+1,sizeof("to")-1,KW_TO,src->current_row,src->current_column); - if(check_and_move_if_on_word("on",sizeof("on")-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_SEMI_COLUMN,src->current_row,src->current_column); - if(check_and_move_if_on_word("|",sizeof("|")-1,src,0)) - return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column); - if(check_and_move_if_on_word("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); - - - - - - - if(IS_ID_CHAR(src->src[src->where_in_src])) /*check for id*/ - { - size_t i; - - ++src->where_in_src; - for( i=src->where_in_src ; - i < src->src_size && IS_ID_THING(src->src[i]); - ++i); - - - i-=src->where_in_src; - src->where_in_src+=i; - return get_token(src->src + src->where_in_src - i - 1, i + 1, KW_ID,src->current_row,src->current_column); - }else if(src->src[src->where_in_src]=='"') /*check for string literal*/ - { - size_t i; - ++src->where_in_src; - for( i=src->where_in_src ; - src->src[i]!='"' && i< src->src_size; - ++i); - - if(i==src->src_size) - { - LEX_ERROR("Unexpected end of file"); - }else - { - i-=src->where_in_src; - src->where_in_src+=i+1; - return get_token(src->src + src->where_in_src-i-1, i, KW_STRING,src->current_row,src->current_column); - } - - }else - { - LEX_ERROR("Unexpected symbol"); - } -} -struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column) -{ - struct token *ret; - ret=malloc(sizeof(struct token)); - ret->data=data; - ret->size=size; - ret->type=type; - ret->row=row; - ret->column=column; - - return ret; -} -void delete_token(struct token *token) -{ - free(token); -} - -/*word_size without the ending '\0' */ -static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after) -{ - size_t i; - if(src->where_in_src + word_size > src->src_size) - return 0; - - for(i=0;isrc[src->where_in_src+i];++i); - - if(isrc[src->where_in_src+i])) || !needs_space_after ) - { - src->where_in_src+=i; - src->current_column+=i; - return 1; - } - else - { - return 0; - } -} -void skip_white_space(struct Source *src) -{ - while(src->where_in_srcsrc_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 diff --git a/lexer.h b/lexer.h deleted file mode 100644 index 320146c..0000000 --- a/lexer.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef LEXER_H -#define LEXER_H -#include //isspace -#include -#include -#include - -struct Translation_Data; -struct Source; - -enum Keyword -{ - KW_MACHINE, - KW_FROM, - KW_TO, - KW_ON, - KW_ID, - KW_STRING, - KW_NOP, - KW_EOF, - KW_OPEN_SQUARE, - KW_CLOSE_SQUARE, - KW_PIPE, - KW_SEMI_COLUMN, - KW_STARTING, - KW_STATES, - KW_EVENTS, - KW_EVENT, - KW_EXECUTE, - KW_TRANSITIONS, - KW_COMMA, -}; -struct token -{ - size_t size; - enum Keyword type; - char *data; - size_t row; - size_t column; -}; - -void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data); -struct token* lex_step(struct Source *src,struct Translation_Data *translation_data); -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); -/*:X*/ -static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after); - -#endif diff --git a/main.c b/main.c deleted file mode 100644 index 438f282..0000000 --- a/main.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include -#include -#include - - - -int main(int argc,char **argv) -{ - struct Options *options; - struct Source *source; - struct Program *program; - struct Translation_Data *translation_data; - struct AST* translation_unit; - - options=parse_command_line(argc,argv); - if(options->src_name==NULL) - { - printf("No source file specified\n"); - return 0; - } - source=extract_source(strndup(options->src_name,100)); - translation_data=get_translation_data(); - - 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 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); - delete_options(options); - return 0; -} diff --git a/makefile b/makefile deleted file mode 100644 index 354eed1..0000000 --- a/makefile +++ /dev/null @@ -1,20 +0,0 @@ -INCLUDE_DIRS=-I . -CFLAGS="-g" -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 - gcc ${CFLAGS} -c queue.c -o queue.o ${INCLUDE_DIRS} -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 parser.o map.o stack.o diff --git a/map.c b/map.c deleted file mode 100644 index cd8272f..0000000 --- a/map.c +++ /dev/null @@ -1,285 +0,0 @@ -#ifndef GMAP_C -#define GMAP_C GMAP_C -#include - - - -/* - * 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; - *wheredelta[((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;tempdelta[((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(tempID; //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;wheredelta[((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(tempID!=NULL)tree->ID=id; - tree->is_final=1; - return tree; - } - - for(temp;tempdelta[((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;tempdelta[((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 diff --git a/map.h b/map.h deleted file mode 100644 index ced43a7..0000000 --- a/map.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef GMAP_H -#define GMAP_H GMAP_H -#include -#include -#include -#include -#include - -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 deleted file mode 100644 index 3e4e449..0000000 --- a/parser.c +++ /dev/null @@ -1,669 +0,0 @@ -#ifndef PARSER_C -#define PARSER_C PARSER_C -#include - -/* - * 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;inumber_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;inumber_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;isize;++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;isize;++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 deleted file mode 100644 index ef82184..0000000 --- a/parser.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H PARSER_H -#include -#include -#include -#include - -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 diff --git a/print.c b/print.c deleted file mode 100644 index 614a6c9..0000000 --- a/print.c +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef PRINT_C -#define PRINT_C PRINT_C -#include - -void print_keyword_enum(enum Keyword code) -{ - switch(code) - { - case KW_MACHINE: - printf("KW_MACHINE"); - break; - case KW_FROM: - printf("KW_FROM"); - break; - case KW_TO: - printf("KW_TO"); - break; - case KW_ON: - printf("KW_ON"); - break; - case KW_ID: - printf("KW_ID"); - break; - case KW_STRING: - printf("KW_STRING"); - break; - case KW_NOP: - printf("KW_NOP"); - break; - case KW_EOF: - printf("KW_EOF"); - break; - case KW_OPEN_SQUARE: - printf("KW_OPEN_SQUARE"); - break; - case KW_CLOSE_SQUARE: - printf("KW_CLOSE_SQUARE"); - break; - case KW_PIPE: - printf("KW_PIPE"); - break; - case KW_SEMI_COLUMN: - printf("KW_SEMI_COLUMN"); - break; - case KW_STARTING: - printf("KW_STARTING"); - break; - case KW_STATES: - printf("KW_STATES"); - break; - case KW_EVENTS: - printf("KW_EVENTS"); - break; - case KW_EVENT: - printf("KW_EVENT"); - break; - case KW_TRANSITIONS: - printf("KW__TRANSITIONS"); - break; - case KW_EXECUTE: - printf("KW_EXECUTE"); - break; - case KW_COMMA: - printf("KW_COMMA"); - break; - default: - printf("LEXERROR"); - } -} -void print_token(struct token *token) -{ - size_t i; - assert(token); - - printf("[ "); - print_keyword_enum(token->type); - printf(" "); - for(i=0;isize;++i) - printf("%c",token->data[i]); - printf(" ] "); - -} -void print_tokens(struct Queue *tokens) -{ - struct Queue_Node *it; - assert(tokens); - - for(it=tokens->first;it!=NULL;it=it->prev) - { - print_token( (struct token*)(it->data)); - printf(" "); - } -} -void print_ast_enum(enum AST_Type type) -{ - switch(type) - { - case AST_TYPE_MACHINE: - printf("AST_TYPE_MACHINE"); - break; - case AST_TYPE_STATE: - printf("AST_TYPE_STATE"); - break; - case AST_TYPE_STATES: - printf("AST_TYPE_STATES"); - break; - case AST_TYPE_EVENT: - printf("AST_TYPE_EVENT"); - break; - case AST_TYPE_EVENTS: - printf("AST_TYPE_EVENTS"); - break; - case AST_TYPE_TRANSITION: - printf("AST_TYPE_TRANSITION"); - break; - case AST_TYPE_TRANSITIONS: - printf("AST_TYPE_TRANSITIONS"); - break; - case AST_TYPE_COMMAND: - printf("AST_TYPE_COMMAND"); - break; - case AST_TYPE_PIPELINE: - printf("AST_TYPE_PIPELINE"); - break; - default: - printf("AST_NOP"); - } - -} -void print_ast(struct AST *tree) -{ - assert(tree); - - switch(tree->type) - { - case AST_TYPE_MACHINE: - print_ast_machine((struct AST_Machine*)tree); - break; - case AST_TYPE_STATE: - print_ast_state((struct AST_State*)tree); - break; - case AST_TYPE_STATES: - print_ast_states((struct AST_States*)tree); - break; - case AST_TYPE_EVENT: - print_ast_event((struct AST_Event*)tree); - break; - case AST_TYPE_EVENTS: - print_ast_events((struct AST_Events*)tree); - break; - case AST_TYPE_TRANSITION: - print_ast_transition((struct AST_Transition*)tree); - break; - case AST_TYPE_TRANSITIONS: - print_ast_transitions((struct AST_Transitions*)tree); - break; - case AST_TYPE_COMMAND: - print_ast_command((struct AST_Command*)tree); - break; - case AST_TYPE_PIPELINE: - print_ast_pipeline((struct AST_Pipeline*)tree); - break; - default: - printf("noast"); - } -} -void print_ast_state(struct AST_State* tree) -{ - assert(tree); - - printf("[ STATE: "); - print_ast_enum(tree->type); - printf("]"); -} -void print_ast_event(struct AST_Event* tree) -{ - assert(tree); - - printf("[ EVENT: "); - print_ast_enum(tree->type); - printf("]"); -} -void print_ast_states(struct AST_States* tree) -{ - size_t i; - assert(tree); - - printf("STATES [\n"); - for(i=0;inumber_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;inumber_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;isize;++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;isize;++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 diff --git a/print.h b/print.h deleted file mode 100644 index 54d47ce..0000000 --- a/print.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef PRINT_H -#define PRINT_H PRINT_H -#include -#include -#include -#include - - -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 diff --git a/program.c b/program.c deleted file mode 100644 index 5cf8cc3..0000000 --- a/program.c +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef PROGRAM_C -#define PROGRAM_C -#include - -struct Source* extract_source(char *src_name) -{ - FILE *file; - - struct Source *ret; - - file=fopen(src_name,"r"); - if(file==NULL) - return NULL; - if(fseek(file,0L,SEEK_END)!=0) - return NULL; - - ret=malloc(sizeof(struct Source)); - ret->src_size=ftell(file); - ret->where_in_src=0; - ret->src_name=src_name; - ret->src=malloc(ret->src_size); - ret->current_column=0; - ret->current_row=0; - - fseek(file,0L,SEEK_SET); - - - fread(ret->src,sizeof(char),ret->src_size,file); - - fclose(file); - return ret; -} -struct Options* parse_command_line(int argc,char **argv) -{ - struct Options *ret; - int i; - - assert(argv!=NULL && argc>0); - - ret=malloc(sizeof(struct Options)); - ret->target=OPTION_DEFAULT; - ret->src_name=NULL; - ret->is_quiet=0; - - for(i=0;itarget=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(++isrc_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 Translation_Data *ret; - ret=malloc(sizeof(struct Translation_Data)); - ret->errors=malloc(sizeof(struct Queue)); - ret->tokens=malloc(sizeof(struct Queue)); - - Queue_Init(ret->errors); - Queue_Init(ret->tokens); - - ret->hold_number_of_errors=0; - - return ret; -} -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+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 Translation_Data *translation_data) -{ - 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) -{ - if(translation_data->hold_number_of_errors!=translation_data->errors->size) - { - translation_data->hold_number_of_errors=translation_data->errors->size; - return 1; - }else - { - return 0; - } -} - -void delete_translation_data(struct Translation_Data *data) -{ - struct Error *hold_error; - struct token *hold_token; - - while(data->tokens->size>0) - delete_token(Queue_Pop(data->tokens)); - free(data->tokens); - while(data->errors->size>0) - delete_error(Queue_Pop(data->errors)); - free(data->errors); - - free(data); -} -void delete_source(struct Source *src) -{ - free(src->src_name); - free(src->src); - free(src); -} -void delete_options(struct Options *options) -{ - free(options); -} -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 diff --git a/program.h b/program.h deleted file mode 100644 index d5e45b7..0000000 --- a/program.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef PROGRAM_H -#define PROGRAM_H -#include -#include -#include -#include -#include -#include - -struct token; -enum Keyword; - -enum Options_Target_Type -{ - OPTION_TARGET_TOKENS, - OPTION_TARGET_AST, - OPTION_DEFAULT, -}; - -struct Source -{ - size_t src_size; - size_t where_in_src; - size_t current_column; - size_t current_row; - char *src_name; - char *src; - -}; - -struct Options -{ - enum Options_Target_Type target; - int is_quiet:1; - char *src_name; -}; - -struct Error -{ - char *message; - size_t row; - size_t column; -}; - -struct Translation_Data -{ - struct Queue *errors; - struct Queue *tokens; - size_t hold_number_of_errors; -}; -struct Program -{ - struct Source *source; - -}; - -struct Source* extract_source(char *src_name); -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 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); -void delete_options(struct Options *options); -void delete_error(struct Error *error); - - -#endif diff --git a/queue.c b/queue.c deleted file mode 100644 index b395acf..0000000 --- a/queue.c +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef GQUEUE_C -#define GQUEUE_C GQUEUE_C -#include - - -void Queue_Init(struct Queue *q) -{ - q->first=q->last=NULL; - q->size=0; -} -void Queue_Push(struct Queue *q,void *data) -{ - if(q==NULL)return; - if(q->first==NULL) - { - q->first=q->last=malloc(sizeof(struct Queue_Node)); - - q->first->data=data; - q->first->prev=NULL; - - ++q->size; - }else - { - struct Queue_Node *temp=malloc(sizeof(struct Queue_Node)); - q->last->prev=temp; - temp->data=data; - temp->prev=NULL; - q->last=temp; - ++q->size; - } - -} -void* Queue_Pop(struct Queue *q) -{ - if(q==NULL)return NULL; - if(q->size==0)return NULL; - - void *return_value=q->first->data; - - if(q->size==1) - { - free(q->last); - q->first=q->last=NULL; - q->size=0; - }else - { - struct Queue_Node *temp_first=q->first; - q->first=q->first->prev; - free(temp_first); - --q->size; - } - return return_value; -} -void Queue_Destroy(struct Queue *q) -{ - - struct Queue_Node *temp_first; - while(q->first!=NULL) - { - temp_first=q->first; - q->first=q->first->prev; - free(temp_first->data); - free(temp_first); - } - -} -#endif diff --git a/queue.h b/queue.h deleted file mode 100644 index 651d4b0..0000000 --- a/queue.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef GQUEUE_H -#define GQUEUE_H GQUEUE_H -#include - - -struct Queue_Node -{ - void *data; - struct Queue_Node *prev; -}; - -struct Queue -{ - struct Queue_Node *first,*last; - size_t size; - -}; - -void Queue_Init(struct Queue *q); -void Queue_Push(struct Queue *q,void *data); -void* Queue_Pop(struct Queue *q); -void Queue_Destroy(struct Queue *q); -#endif diff --git a/src/backend/print.c b/src/backend/print.c new file mode 100644 index 0000000..614a6c9 --- /dev/null +++ b/src/backend/print.c @@ -0,0 +1,294 @@ +#ifndef PRINT_C +#define PRINT_C PRINT_C +#include + +void print_keyword_enum(enum Keyword code) +{ + switch(code) + { + case KW_MACHINE: + printf("KW_MACHINE"); + break; + case KW_FROM: + printf("KW_FROM"); + break; + case KW_TO: + printf("KW_TO"); + break; + case KW_ON: + printf("KW_ON"); + break; + case KW_ID: + printf("KW_ID"); + break; + case KW_STRING: + printf("KW_STRING"); + break; + case KW_NOP: + printf("KW_NOP"); + break; + case KW_EOF: + printf("KW_EOF"); + break; + case KW_OPEN_SQUARE: + printf("KW_OPEN_SQUARE"); + break; + case KW_CLOSE_SQUARE: + printf("KW_CLOSE_SQUARE"); + break; + case KW_PIPE: + printf("KW_PIPE"); + break; + case KW_SEMI_COLUMN: + printf("KW_SEMI_COLUMN"); + break; + case KW_STARTING: + printf("KW_STARTING"); + break; + case KW_STATES: + printf("KW_STATES"); + break; + case KW_EVENTS: + printf("KW_EVENTS"); + break; + case KW_EVENT: + printf("KW_EVENT"); + break; + case KW_TRANSITIONS: + printf("KW__TRANSITIONS"); + break; + case KW_EXECUTE: + printf("KW_EXECUTE"); + break; + case KW_COMMA: + printf("KW_COMMA"); + break; + default: + printf("LEXERROR"); + } +} +void print_token(struct token *token) +{ + size_t i; + assert(token); + + printf("[ "); + print_keyword_enum(token->type); + printf(" "); + for(i=0;isize;++i) + printf("%c",token->data[i]); + printf(" ] "); + +} +void print_tokens(struct Queue *tokens) +{ + struct Queue_Node *it; + assert(tokens); + + for(it=tokens->first;it!=NULL;it=it->prev) + { + print_token( (struct token*)(it->data)); + printf(" "); + } +} +void print_ast_enum(enum AST_Type type) +{ + switch(type) + { + case AST_TYPE_MACHINE: + printf("AST_TYPE_MACHINE"); + break; + case AST_TYPE_STATE: + printf("AST_TYPE_STATE"); + break; + case AST_TYPE_STATES: + printf("AST_TYPE_STATES"); + break; + case AST_TYPE_EVENT: + printf("AST_TYPE_EVENT"); + break; + case AST_TYPE_EVENTS: + printf("AST_TYPE_EVENTS"); + break; + case AST_TYPE_TRANSITION: + printf("AST_TYPE_TRANSITION"); + break; + case AST_TYPE_TRANSITIONS: + printf("AST_TYPE_TRANSITIONS"); + break; + case AST_TYPE_COMMAND: + printf("AST_TYPE_COMMAND"); + break; + case AST_TYPE_PIPELINE: + printf("AST_TYPE_PIPELINE"); + break; + default: + printf("AST_NOP"); + } + +} +void print_ast(struct AST *tree) +{ + assert(tree); + + switch(tree->type) + { + case AST_TYPE_MACHINE: + print_ast_machine((struct AST_Machine*)tree); + break; + case AST_TYPE_STATE: + print_ast_state((struct AST_State*)tree); + break; + case AST_TYPE_STATES: + print_ast_states((struct AST_States*)tree); + break; + case AST_TYPE_EVENT: + print_ast_event((struct AST_Event*)tree); + break; + case AST_TYPE_EVENTS: + print_ast_events((struct AST_Events*)tree); + break; + case AST_TYPE_TRANSITION: + print_ast_transition((struct AST_Transition*)tree); + break; + case AST_TYPE_TRANSITIONS: + print_ast_transitions((struct AST_Transitions*)tree); + break; + case AST_TYPE_COMMAND: + print_ast_command((struct AST_Command*)tree); + break; + case AST_TYPE_PIPELINE: + print_ast_pipeline((struct AST_Pipeline*)tree); + break; + default: + printf("noast"); + } +} +void print_ast_state(struct AST_State* tree) +{ + assert(tree); + + printf("[ STATE: "); + print_ast_enum(tree->type); + printf("]"); +} +void print_ast_event(struct AST_Event* tree) +{ + assert(tree); + + printf("[ EVENT: "); + print_ast_enum(tree->type); + printf("]"); +} +void print_ast_states(struct AST_States* tree) +{ + size_t i; + assert(tree); + + printf("STATES [\n"); + for(i=0;inumber_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;inumber_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;isize;++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;isize;++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 diff --git a/src/backend/print.h b/src/backend/print.h new file mode 100644 index 0000000..54d47ce --- /dev/null +++ b/src/backend/print.h @@ -0,0 +1,27 @@ +#ifndef PRINT_H +#define PRINT_H PRINT_H +#include +#include +#include +#include + + +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 diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c new file mode 100644 index 0000000..6dc348d --- /dev/null +++ b/src/frontend/lexer.c @@ -0,0 +1,160 @@ +#ifndef LEXER_C +#define LEXER_C +#include + +#define IS_ID_CHAR(x) ( (x <= 'z' && x>='a') || ( x <= 'Z' && x >= 'A' ) || x=='_') +#define IS_DIGIT(x) ( x <= '9' && x >= '0' ) +#define IS_ID_THING(x) ( IS_ID_CHAR(x) || IS_DIGIT(x)) +#define LEX_ERROR(x) {push_lexing_error(x,src,translation_data); return get_token(src->src+src->where_in_src,0,KW_NOP,src->current_row,src->current_column);} + +/* + * placeholder very slow lexer that I will probabbly not replace + */ +void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data) +{ + skip_white_space(src); + while(src->where_in_srcsrc_size) + { + Queue_Push(token_destination,lex_step(src,translation_data)); + if(has_new_errors(translation_data)) + return; + else + skip_white_space(src); + } + Queue_Push(token_destination,get_token(NULL,0,KW_EOF,src->current_row,src->current_column)); +} + + +struct token* lex_step(struct Source *src,struct Translation_Data *translation_data) +{ + 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("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("to")+1,sizeof("to")-1,KW_TO,src->current_row,src->current_column); + if(check_and_move_if_on_word("on",sizeof("on")-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_SEMI_COLUMN,src->current_row,src->current_column); + if(check_and_move_if_on_word("|",sizeof("|")-1,src,0)) + return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column); + if(check_and_move_if_on_word("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); + + + + + + + if(IS_ID_CHAR(src->src[src->where_in_src])) /*check for id*/ + { + size_t i; + + ++src->where_in_src; + for( i=src->where_in_src ; + i < src->src_size && IS_ID_THING(src->src[i]); + ++i); + + + i-=src->where_in_src; + src->where_in_src+=i; + return get_token(src->src + src->where_in_src - i - 1, i + 1, KW_ID,src->current_row,src->current_column); + }else if(src->src[src->where_in_src]=='"') /*check for string literal*/ + { + size_t i; + ++src->where_in_src; + for( i=src->where_in_src ; + src->src[i]!='"' && i< src->src_size; + ++i); + + if(i==src->src_size) + { + LEX_ERROR("Unexpected end of file"); + }else + { + i-=src->where_in_src; + src->where_in_src+=i+1; + return get_token(src->src + src->where_in_src-i-1, i, KW_STRING,src->current_row,src->current_column); + } + + }else + { + LEX_ERROR("Unexpected symbol"); + } +} +struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column) +{ + struct token *ret; + ret=malloc(sizeof(struct token)); + ret->data=data; + ret->size=size; + ret->type=type; + ret->row=row; + ret->column=column; + + return ret; +} +void delete_token(struct token *token) +{ + free(token); +} + +/*word_size without the ending '\0' */ +static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after) +{ + size_t i; + if(src->where_in_src + word_size > src->src_size) + return 0; + + for(i=0;isrc[src->where_in_src+i];++i); + + if(isrc[src->where_in_src+i])) || !needs_space_after ) + { + src->where_in_src+=i; + src->current_column+=i; + return 1; + } + else + { + return 0; + } +} +void skip_white_space(struct Source *src) +{ + while(src->where_in_srcsrc_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 diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h new file mode 100644 index 0000000..320146c --- /dev/null +++ b/src/frontend/lexer.h @@ -0,0 +1,54 @@ +#ifndef LEXER_H +#define LEXER_H +#include //isspace +#include +#include +#include + +struct Translation_Data; +struct Source; + +enum Keyword +{ + KW_MACHINE, + KW_FROM, + KW_TO, + KW_ON, + KW_ID, + KW_STRING, + KW_NOP, + KW_EOF, + KW_OPEN_SQUARE, + KW_CLOSE_SQUARE, + KW_PIPE, + KW_SEMI_COLUMN, + KW_STARTING, + KW_STATES, + KW_EVENTS, + KW_EVENT, + KW_EXECUTE, + KW_TRANSITIONS, + KW_COMMA, +}; +struct token +{ + size_t size; + enum Keyword type; + char *data; + size_t row; + size_t column; +}; + +void lex(struct Queue *token_destination,struct Source *src,struct Translation_Data *translation_data); +struct token* lex_step(struct Source *src,struct Translation_Data *translation_data); +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); +/*:X*/ +static char check_and_move_if_on_word(char *word,size_t word_size,struct Source *src,char needs_space_after); + +#endif diff --git a/src/frontend/parser.c b/src/frontend/parser.c new file mode 100644 index 0000000..3e4e449 --- /dev/null +++ b/src/frontend/parser.c @@ -0,0 +1,669 @@ +#ifndef PARSER_C +#define PARSER_C PARSER_C +#include + +/* + * 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;inumber_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;inumber_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;isize;++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;isize;++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/src/frontend/parser.h b/src/frontend/parser.h new file mode 100644 index 0000000..ef82184 --- /dev/null +++ b/src/frontend/parser.h @@ -0,0 +1,124 @@ +#ifndef PARSER_H +#define PARSER_H PARSER_H +#include +#include +#include +#include + +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 diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..438f282 --- /dev/null +++ b/src/main.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + + + +int main(int argc,char **argv) +{ + struct Options *options; + struct Source *source; + struct Program *program; + struct Translation_Data *translation_data; + struct AST* translation_unit; + + options=parse_command_line(argc,argv); + if(options->src_name==NULL) + { + printf("No source file specified\n"); + return 0; + } + source=extract_source(strndup(options->src_name,100)); + translation_data=get_translation_data(); + + 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 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); + delete_options(options); + return 0; +} diff --git a/src/misc/map.c b/src/misc/map.c new file mode 100644 index 0000000..cd8272f --- /dev/null +++ b/src/misc/map.c @@ -0,0 +1,285 @@ +#ifndef GMAP_C +#define GMAP_C GMAP_C +#include + + + +/* + * 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; + *wheredelta[((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;tempdelta[((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(tempID; //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;wheredelta[((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(tempID!=NULL)tree->ID=id; + tree->is_final=1; + return tree; + } + + for(temp;tempdelta[((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;tempdelta[((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 diff --git a/src/misc/map.h b/src/misc/map.h new file mode 100644 index 0000000..ced43a7 --- /dev/null +++ b/src/misc/map.h @@ -0,0 +1,41 @@ +#ifndef GMAP_H +#define GMAP_H GMAP_H +#include +#include +#include +#include +#include + +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/src/misc/queue.c b/src/misc/queue.c new file mode 100644 index 0000000..b395acf --- /dev/null +++ b/src/misc/queue.c @@ -0,0 +1,67 @@ +#ifndef GQUEUE_C +#define GQUEUE_C GQUEUE_C +#include + + +void Queue_Init(struct Queue *q) +{ + q->first=q->last=NULL; + q->size=0; +} +void Queue_Push(struct Queue *q,void *data) +{ + if(q==NULL)return; + if(q->first==NULL) + { + q->first=q->last=malloc(sizeof(struct Queue_Node)); + + q->first->data=data; + q->first->prev=NULL; + + ++q->size; + }else + { + struct Queue_Node *temp=malloc(sizeof(struct Queue_Node)); + q->last->prev=temp; + temp->data=data; + temp->prev=NULL; + q->last=temp; + ++q->size; + } + +} +void* Queue_Pop(struct Queue *q) +{ + if(q==NULL)return NULL; + if(q->size==0)return NULL; + + void *return_value=q->first->data; + + if(q->size==1) + { + free(q->last); + q->first=q->last=NULL; + q->size=0; + }else + { + struct Queue_Node *temp_first=q->first; + q->first=q->first->prev; + free(temp_first); + --q->size; + } + return return_value; +} +void Queue_Destroy(struct Queue *q) +{ + + struct Queue_Node *temp_first; + while(q->first!=NULL) + { + temp_first=q->first; + q->first=q->first->prev; + free(temp_first->data); + free(temp_first); + } + +} +#endif diff --git a/src/misc/queue.h b/src/misc/queue.h new file mode 100644 index 0000000..651d4b0 --- /dev/null +++ b/src/misc/queue.h @@ -0,0 +1,23 @@ +#ifndef GQUEUE_H +#define GQUEUE_H GQUEUE_H +#include + + +struct Queue_Node +{ + void *data; + struct Queue_Node *prev; +}; + +struct Queue +{ + struct Queue_Node *first,*last; + size_t size; + +}; + +void Queue_Init(struct Queue *q); +void Queue_Push(struct Queue *q,void *data); +void* Queue_Pop(struct Queue *q); +void Queue_Destroy(struct Queue *q); +#endif diff --git a/src/misc/stack.c b/src/misc/stack.c new file mode 100644 index 0000000..272732f --- /dev/null +++ b/src/misc/stack.c @@ -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 + diff --git a/src/misc/stack.h b/src/misc/stack.h new file mode 100644 index 0000000..14e557a --- /dev/null +++ b/src/misc/stack.h @@ -0,0 +1,22 @@ +#ifndef GSTACK_H +#define GSTACK_H GSTACK_H +#include +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 diff --git a/src/program/program.c b/src/program/program.c new file mode 100644 index 0000000..5cf8cc3 --- /dev/null +++ b/src/program/program.c @@ -0,0 +1,183 @@ +#ifndef PROGRAM_C +#define PROGRAM_C +#include + +struct Source* extract_source(char *src_name) +{ + FILE *file; + + struct Source *ret; + + file=fopen(src_name,"r"); + if(file==NULL) + return NULL; + if(fseek(file,0L,SEEK_END)!=0) + return NULL; + + ret=malloc(sizeof(struct Source)); + ret->src_size=ftell(file); + ret->where_in_src=0; + ret->src_name=src_name; + ret->src=malloc(ret->src_size); + ret->current_column=0; + ret->current_row=0; + + fseek(file,0L,SEEK_SET); + + + fread(ret->src,sizeof(char),ret->src_size,file); + + fclose(file); + return ret; +} +struct Options* parse_command_line(int argc,char **argv) +{ + struct Options *ret; + int i; + + assert(argv!=NULL && argc>0); + + ret=malloc(sizeof(struct Options)); + ret->target=OPTION_DEFAULT; + ret->src_name=NULL; + ret->is_quiet=0; + + for(i=0;itarget=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(++isrc_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 Translation_Data *ret; + ret=malloc(sizeof(struct Translation_Data)); + ret->errors=malloc(sizeof(struct Queue)); + ret->tokens=malloc(sizeof(struct Queue)); + + Queue_Init(ret->errors); + Queue_Init(ret->tokens); + + ret->hold_number_of_errors=0; + + return ret; +} +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+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 Translation_Data *translation_data) +{ + 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) +{ + if(translation_data->hold_number_of_errors!=translation_data->errors->size) + { + translation_data->hold_number_of_errors=translation_data->errors->size; + return 1; + }else + { + return 0; + } +} + +void delete_translation_data(struct Translation_Data *data) +{ + struct Error *hold_error; + struct token *hold_token; + + while(data->tokens->size>0) + delete_token(Queue_Pop(data->tokens)); + free(data->tokens); + while(data->errors->size>0) + delete_error(Queue_Pop(data->errors)); + free(data->errors); + + free(data); +} +void delete_source(struct Source *src) +{ + free(src->src_name); + free(src->src); + free(src); +} +void delete_options(struct Options *options) +{ + free(options); +} +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 diff --git a/src/program/program.h b/src/program/program.h new file mode 100644 index 0000000..d5e45b7 --- /dev/null +++ b/src/program/program.h @@ -0,0 +1,76 @@ +#ifndef PROGRAM_H +#define PROGRAM_H +#include +#include +#include +#include +#include +#include + +struct token; +enum Keyword; + +enum Options_Target_Type +{ + OPTION_TARGET_TOKENS, + OPTION_TARGET_AST, + OPTION_DEFAULT, +}; + +struct Source +{ + size_t src_size; + size_t where_in_src; + size_t current_column; + size_t current_row; + char *src_name; + char *src; + +}; + +struct Options +{ + enum Options_Target_Type target; + int is_quiet:1; + char *src_name; +}; + +struct Error +{ + char *message; + size_t row; + size_t column; +}; + +struct Translation_Data +{ + struct Queue *errors; + struct Queue *tokens; + size_t hold_number_of_errors; +}; +struct Program +{ + struct Source *source; + +}; + +struct Source* extract_source(char *src_name); +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 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); +void delete_options(struct Options *options); +void delete_error(struct Error *error); + + +#endif diff --git a/stack.c b/stack.c deleted file mode 100644 index 272732f..0000000 --- a/stack.c +++ /dev/null @@ -1,37 +0,0 @@ -#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 - diff --git a/stack.h b/stack.h deleted file mode 100644 index 14e557a..0000000 --- a/stack.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef GSTACK_H -#define GSTACK_H GSTACK_H -#include -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 diff --git a/test b/test deleted file mode 100644 index c976a6d..0000000 --- a/test +++ /dev/null @@ -1,16 +0,0 @@ -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; - ]; -]; - diff --git a/test2 b/test2 deleted file mode 100644 index a5342f0..0000000 --- a/test2 +++ /dev/null @@ -1,2 +0,0 @@ -"1" -"12" diff --git a/test3 b/test3 deleted file mode 100644 index 43e47d1..0000000 --- a/test3 +++ /dev/null @@ -1,21 +0,0 @@ -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() -{ - -} diff --git a/tests/test b/tests/test new file mode 100644 index 0000000..c976a6d --- /dev/null +++ b/tests/test @@ -0,0 +1,16 @@ +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; + ]; +]; + diff --git a/tests/test2 b/tests/test2 new file mode 100644 index 0000000..a5342f0 --- /dev/null +++ b/tests/test2 @@ -0,0 +1,2 @@ +"1" +"12" diff --git a/tests/test3 b/tests/test3 new file mode 100644 index 0000000..43e47d1 --- /dev/null +++ b/tests/test3 @@ -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() +{ + +} -- cgit v1.2.3