MEGATRON



LOG | FILES | OVERVIEW


F diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore
tags
*.exe
*.o
+ build
F diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/CMakeLists.txt
+ 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})
F diff --git a/lexer.c b/lexer.c deleted file mode 100644 --- a/lexer.c +++ /dev/null
- #ifndef LEXER_C
- #define LEXER_C
- #include <lexer.h>
-
- #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_src<src->src_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;i<word_size && word[i]==src->src[src->where_in_src+i];++i);
-
- if(i<word_size)
- {
- return 0;
- }
- else if( (needs_space_after && isspace(src->src[src->where_in_src+i])) || !needs_space_after )
- {
- src->where_in_src+=i;
- src->current_column+=i;
- return 1;
- }
- else
- {
- return 0;
- }
- }
- void skip_white_space(struct Source *src)
- {
- while(src->where_in_src<src->src_size && isspace(src->src[src->where_in_src]))
- {
- if(src->src[src->where_in_src]=='\n')
- {
- ++src->current_row;
- src->current_column=0;
- }
- ++src->where_in_src;
- }
- }
-
- void push_token_into_map(struct token *token,struct Map *map,void *thing)
- {
- Map_Push(map,token->data,token->size,thing);
- }
- #endif
F diff --git a/lexer.h b/lexer.h deleted file mode 100644 --- a/lexer.h +++ /dev/null
- #ifndef LEXER_H
- #define LEXER_H
- #include <ctype.h> //isspace
- #include <program.h>
- #include <queue.h>
- #include <map.h>
-
- struct Translation_Data;
- struct Source;
-
- enum Keyword
- {
- KW_MACHINE,
- KW_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
F diff --git a/main.c b/main.c deleted file mode 100644 --- a/main.c +++ /dev/null
- #include <stdio.h>
- #include <program.h>
- #include <lexer.h>
- #include <string.h>
- #include <parser.h>
- #include <print.h>
-
-
-
- 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;
- }
F diff --git a/makefile b/makefile deleted file mode 100644 --- a/makefile +++ /dev/null
- 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
F diff --git a/map.c b/map.c deleted file mode 100644 --- a/map.c +++ /dev/null
- #ifndef GMAP_C
- #define GMAP_C GMAP_C
- #include <map.h>
-
-
-
- /*
- * ID and residue and all of delta is assigned to NULL
- * */
- void Map_Init(Map *tree)
- {
- tree->is_final=0;
- for(int i=0;i<256;++i)tree->delta[i] = NULL;
- tree->ID = NULL;
- }
-
- void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node)
- {
- for(
- *where=0,*final_node=tree;
- *where<size && final_node[0]->delta[((unsigned char*)str)[ where[0] ]]!=NULL;
- ++where[0]
- )
- {
- (*final_node) = (*final_node)->delta[((unsigned char*)str)[*where]];
- }
- }
-
-
-
- /*
- * tree must not be null
- * */
- void Map_Push(Map *tree,void *str,size_t size,void *id)
- {
- size_t temp;
- Map_Scour(tree,str,size,&temp,&tree);
-
- if(temp == size)
- {
- assert(tree->ID==NULL);
- tree->ID=id;
- tree->is_final=1;
- return;
- }
- for(temp;temp<size;++temp)
- {
- tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
- /*
- Map_Init(
- tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
- );
- */
- }
-
- tree->ID=id;
- tree->is_final=1;
-
- }
-
-
- /*
- * scours the tree and returns the id of the node that recognises the str
- * returns NULL if the string is not recognised
- * */
- void* Map_Check(Map *tree, void *str,size_t size)
- {
- size_t temp;
- Map_Scour(tree,str,size,&temp,&tree);
-
- if(temp<size)
- {
- return NULL;
- }else
- {
- return tree->ID; //this has been set to be the last reached node
- }
- }
-
- void Map_Remove(Map *tree, void *str,size_t size)
- {
- Stack stk;
- Stack_Init(&stk);
- size_t where;
- char what_to_null=((char*)str)[0];
-
- Stack_Push(&stk,tree);
-
- for(where=0;where<size-1 && tree->delta[((unsigned char*)str)[where]]!=NULL;++where)
- {
- tree = tree->delta[((unsigned char*)str)[where]];
- if(tree->is_final==1)
- {
- while(stk.size>0)Stack_Pop(&stk);
- what_to_null=((char*)str)[where+1];
- }
- Stack_Push(&stk,tree);
- }
- if(tree->delta[((unsigned char*)str)[where]] == NULL)return;
- free(tree->delta[((unsigned char*)str)[where]]);
- while(stk.size>1)free(Stack_Pop(&stk));
- tree=(Map*)Stack_Pop(&stk);
- tree->delta[(unsigned char)what_to_null]=NULL;
-
- }
- /*This function especially requires that the map has no loops*/
- void Map_Map(Map *tree,void (*map)(void*))
- {
- if(tree->is_final==1)map(tree->ID);
- for(int i=0;i<256;++i)
- {
- if(tree->delta[i]!=NULL)
- {
- Map_Map(tree->delta[i],map);
- }
- }
- }
-
- /*first argument of map is the node id , the second is pass_data*/
- void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data)
- {
- if(tree->is_final==1)map(tree->ID,pass_data);
- for(int i=0;i<256;++i)
- {
- if(tree->delta[i]!=NULL)
- {
- Map_Map_Extended(tree->delta[i],map,pass_data);
- }
- }
- }
-
-
- /*this does not destroy(free) any memory pointed to by a node in the Map. This does not free() the root (Map *tree) */
- /*This function especially does not require that the map has no loop ( for example after grepification )*/
- void Map_Destroy(Map *tree)
- {
- Stack path;
- Stack nodes;
- Map *current_node;
- unsigned int i;
-
-
- Stack_Init(&path);
- Stack_Init(&nodes);
-
- Stack_Push(&path,tree);
- Stack_Push(&nodes,tree);
-
- /*
- using DFS we fill up the nodes stack with all the used
- (accessible) nodes.
- */
- while(path.size>0)
- {
- current_node=Stack_Pop(&path);
- current_node->ID=&(current_node->ID);/*mark the node*/
- for(i=0;i<256;++i)
- {
- if(current_node->delta[i]!=NULL && current_node->delta[i]->ID != &(current_node->delta[i]->ID) )
- {
- Stack_Push(&path,current_node->delta[i]);
-
-
- /*we mark the unmarked child of the current_node*/
- current_node->delta[i]->ID=&(current_node->delta[i]->ID);
- /*every node in nodes continues to be marked*/
- Stack_Push(&nodes,current_node->delta[i]);
- }
- }
-
- }
- /*
- There should not be any duplicates in here
- */
- while(nodes.size>1)
- {
- current_node=Stack_Pop(&nodes);
- /*Again the things that ID points to is not freed ( this structure is used to map the structure of data )
- deletion of it is up to you.
- */
- free(current_node);
- }
- /*this is where the root is at- we don't delete it , but we must free the last stack node*/
- Stack_Pop(&nodes);
-
-
- }
-
- /*requres that cpy has no loops*/
- Map* Map_Copy(Map *cpy)
- {
- short i;
- Map *ret;
-
- if(cpy==NULL)
- {
- return NULL;
- }
-
- ret=malloc(sizeof(Map));
- ret->is_final=cpy->is_final;
- ret->ID=cpy->ID;
-
- for(i=0;i<256;++i)
- {
- ret->delta[i]=Map_Copy(cpy->delta[i]);
- }
- return ret;
- }
-
- struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size)
- {
- size_t temp;
- Map_Scour(tree,str,size,&temp,&tree);
-
- if(temp<size)
- {
- return NULL;
- }else
- {
- return tree;
- }
- }
-
- struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id)
- {
- size_t temp;
- Map_Scour(tree,str,size,&temp,&tree);
-
- if(temp == size)
- {
- if(tree->ID!=NULL)tree->ID=id;
- tree->is_final=1;
- return tree;
- }
-
- for(temp;temp<size;++temp)
- {
- Map_Init(
- tree=
- tree->delta[((unsigned char*)str)[temp]]=
- malloc(sizeof(Map))
- );
- }
-
- tree->ID=id;
- tree->is_final=1;
- return tree;
- }
-
- void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id)
- {
- size_t temp;
- Map_Scour(tree,str,size,&temp,&tree);
-
- if(temp == size)
- {
- if(!tree->is_final)
- {
- tree->ID=id;
- tree->is_final=1;
- }
- return tree->ID;
- }
- for(temp;temp<size;++temp)
- {
- tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
- /*
- Map_Init(
- tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
- );
- */
- }
-
- tree->ID=id;
- tree->is_final=1;
- return NULL;
- }
- /*requires that the map has no loops. does not free the root node*/
- /*TODO*/
- void Map_Delete_Map(struct Map *tree)
- {
-
- }
- #endif //#ifndef GMAP
F diff --git a/map.h b/map.h deleted file mode 100644 --- a/map.h +++ /dev/null
- #ifndef GMAP_H
- #define GMAP_H GMAP_H
- #include <stdlib.h>
- #include <stdio.h>
- #include <stack.h>
- #include <queue.h>
- #include <assert.h>
-
- typedef struct Map Map;
-
-
-
- /*
- * A looples automata with things attached to the nodes
- * */
- struct Map
- {
- char is_final;
- Map *delta[256];
- /*ID cannot point to itself ( this is used in the deletion of the map ) */
- void *ID;
- };
-
- void Map_Init(Map *tree);
- void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node);
- void Map_Push(Map *tree,void *str,size_t size,void *id);
- void* Map_Check(Map *tree, void *str,size_t size);
- struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size);
- void Map_Remove(Map *tree, void *str,size_t size);
- void Map_Map(Map *tree,void (*map)(void*));
- void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);
-
- void Map_Destroy(Map *tree);
- void Map_Delete_Map(struct Map *tree);
- struct Condensed_Map* Map_Condense(Map* tree);
-
- struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id);
- /*returns NULL if id is not taken , returns pointer to taken id otherwise*/
- void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id);
-
- #endif
F diff --git a/parser.c b/parser.c deleted file mode 100644 --- a/parser.c +++ /dev/null
- #ifndef PARSER_C
- #define PARSER_C PARSER_C
- #include <parser.h>
-
- /*
- * parse-unit: machine
- *
- */
- struct AST* parse_unit(struct Translation_Data *translation_data)
- {
- return (struct AST*)parse_machine(translation_data);
- }
- /*
- * machine: 'machine' id '[' machine-inner ']' ';'
- *
- */
- struct AST_Machine* parse_machine(struct Translation_Data *translation_data)
- {
- struct AST_Machine *ret;
- struct token *hold_id;
- if(get_and_check(translation_data,KW_MACHINE))
- {
- if(get_kw(translation_data)==KW_ID)
- {
- hold_id=Queue_Pop(translation_data->tokens);
- if(get_and_check(translation_data,KW_OPEN_SQUARE))
- {
- ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data);
- if(has_new_errors(translation_data))
- {
- delete_ast_machine(ret);
- touch_errors(translation_data);
-
- return NULL;
- }
- if(get_and_check(translation_data,KW_CLOSE_SQUARE))
- {
- if(get_and_check(translation_data,KW_SEMI_COLUMN))
- return ret;
- else
- {
- push_parsing_error("';' expected after machine definition",translation_data);
- delete_ast_machine(ret);
- return NULL;
- }
- }else
- {
- push_parsing_error("closing ']' expected",translation_data);
- delete_ast_machine(ret);
- return NULL;
- }
- }else
- {
- push_parsing_error("opening '[' expected",translation_data);
- return NULL;
- }
- }else
- {
- push_parsing_error("expected a name for the machine",translation_data);
- return NULL;
- }
- }else
- {
- push_parsing_error("'machine' expected",translation_data);
- return NULL;
- }
- }
- /*
- * machine-inner : 'states' '[' states-inner ']' ';'
- * 'events' '[' events-inner ']' ';'
- * 'transitions' '[' transitions-inner ']' ';'
- * 'starting' start-on-inner ';'
- */
- struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data)
- {
- struct AST_States *states=NULL;
- struct AST_Events *events=NULL;
- struct AST_Transitions *transitions=NULL;
- struct AST_State *starting_state=NULL;
- unsigned char i;
- for(i=0;i<4;++i)
- switch(get_kw(translation_data))
- {
- case KW_STATES:
- if(states)
- {
- push_parsing_error("defining two sets of states",translation_data);
- goto error_cleanup;
- }else
- {
- chomp(translation_data);
- if(get_and_check(translation_data,KW_OPEN_SQUARE))
- {
- states=parse_states_inner(translation_data);
- if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
- || !get_and_check(translation_data,KW_SEMI_COLUMN))
- {
- push_parsing_error("expected ']' and ';' at "
- "end of states definition",translation_data);
- goto error_cleanup;
- }
-
- }else
- {
- push_parsing_error("expected '[' ",translation_data);
- goto error_cleanup;
- }
- }
- break;
- case KW_TRANSITIONS:
- if(states==NULL && events==NULL)
- {
- push_parsing_error("defining transitions before states and events",translation_data);
- goto error_cleanup;
- }else if(transitions)
- {
- push_parsing_error("defining two sets of transitions",translation_data);
- goto error_cleanup;
- }else
- {
- chomp(translation_data);
- if(get_and_check(translation_data,KW_OPEN_SQUARE))
- {
- transitions=parse_transitions_inner(translation_data,states,events);
- if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
- || !get_and_check(translation_data,KW_SEMI_COLUMN))
- {
- push_parsing_error("expected ']' and ';' at "
- "end of transitions definition",translation_data);
- goto error_cleanup;
- }
- }else
- {
- push_parsing_error("expected '[' ",translation_data);
- goto error_cleanup;
- }
- }
- break;
- case KW_EVENTS:
- if(events)
- {
- push_parsing_error("defining two sets of transitions",translation_data);
- goto error_cleanup;
- }else
- {
- chomp(translation_data);
- if(get_and_check(translation_data,KW_OPEN_SQUARE))
- {
- events=parse_events_inner(translation_data);
- if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
- || !get_and_check(translation_data,KW_SEMI_COLUMN))
- {
- push_parsing_error("expected ']' and ';' at "
- "end of events definition",translation_data);
- goto error_cleanup;
- }
- }else
- {
- push_parsing_error("expected '[' ",translation_data);
- goto error_cleanup;
- }
- }
- break;
- case KW_STARTING:
- chomp(translation_data);
- if(!starting_state)
- {
- if(states)
- {
- starting_state=parse_start_on(translation_data,states);
- if(!get_and_check(translation_data,KW_SEMI_COLUMN))
- {
- push_parsing_error("expected ';' at end "
- "of starting state declaration",translation_data);
- goto error_cleanup;
- }
- }else
- {
- push_parsing_error("states need to be defined"
- " before defining a starting one",translation_data);
- goto error_cleanup;
- }
- }else
- {
- push_parsing_error("starting state is defined",translation_data);
- goto error_cleanup;
- }
- break;
- default:
- push_parsing_error("expected states transitions or events",translation_data);
- goto error_cleanup;
-
- }
-
- return get_ast_machine(machine_id,states,events,transitions,starting_state);
-
- error_cleanup:
- push_parsing_error("in machine",translation_data);
- if(states)delete_ast_states(states);
- if(events)delete_ast_events(events);
- if(transitions)delete_ast_transitions(transitions);
- return NULL;
- }
- /*
- * states-inner: state (, state)*
- *
- */
- struct AST_States* parse_states_inner(struct Translation_Data *translation_data)
- {
- struct Queue *ids;
- struct AST_State *hold_state;
-
- ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA);
- if(ids->size==0)
- {
- push_parsing_error("there needs to be atleast one state",translation_data);
- free(ids);
- return NULL;
- }else
- {
-
- return get_ast_states(ids);
- }
- }
- /*
- * state : id
- *
- */
- struct AST_State* parse_state(struct Translation_Data *translation_data)
- {
- if(get_kw(translation_data)==KW_ID)
- return get_ast_state(Queue_Pop(translation_data->tokens));
- else
- return NULL;
- }
- /*
- * events-inner: id (, id)*
- *
- */
- struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)
- {
- struct Queue *ids;
- ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA);
- if(ids->size==0)
- {
- push_parsing_error("there needs to be atleast one event",translation_data);
- return NULL;
- }else
- {
- return get_ast_events(ids);
- }
- }
- struct AST_Event* parse_event(struct Translation_Data *translation_data)
- {
- if(get_kw(translation_data)==KW_ID)
- return get_ast_event(Queue_Pop(translation_data->tokens));
- else
- return NULL;
- }
- /*
- * transitions-inner: ( transition ;)*
- */
- struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
- {
- struct Queue *transitions;
- struct AST_Transition *hold_transition;
-
- transitions=malloc(sizeof(struct Queue));
- Queue_Init(transitions);
-
- while((hold_transition=parse_transition(translation_data,states,events))!=NULL)
- {
- Queue_Push(transitions,hold_transition);
- if(!get_and_check(translation_data,KW_SEMI_COLUMN))
- break;
- }
-
- if(transitions->size==0)
- {
- push_parsing_error("there are no transitions",translation_data);
- return NULL;
- }else
- {
- return get_ast_transitions(transitions);
- }
- }
- /*
- * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ]
- *
- */
- struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
- {
- struct AST_Transition *ret;
- struct AST_State *hold_from;
- struct AST_State *hold_to;
- struct AST_Event *hold_event;
- struct AST_Pipeline *hold_pipeline=NULL;
- struct token *hold_token;
-
- if(get_and_check(translation_data,KW_FROM))
- {
- if(get_kw(translation_data)==KW_ID)
- {
- hold_token=Queue_Pop(translation_data->tokens);
- hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_from!=NULL)
- {
- if(get_and_check(translation_data,KW_TO))
- {
- if(get_kw(translation_data)==KW_ID)
- {
- hold_token=Queue_Pop(translation_data->tokens);
- hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_to!=NULL)
- {
- if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
- {
- if(get_kw(translation_data)==KW_ID)
- {
- hold_token=Queue_Pop(translation_data->tokens);
- hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
- delete_token(hold_token);
- if(hold_event!=NULL)
- {
- if(get_and_check(translation_data,KW_EXECUTE))
- if((hold_pipeline=parse_pipeline(translation_data))==NULL)
- { push_parsing_error("after execute",translation_data); return NULL; }
- /*GOAL*/
- return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
- }else { push_parsing_error("event not defined",translation_data); return NULL; }
- }else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
- }else { push_parsing_error("expected 'on event'",translation_data); return NULL; }
- }else { push_parsing_error("using undefined to state in transition",translation_data); }
- }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
- }else { push_parsing_error("expected 'to'",translation_data); return NULL; }
- }else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
- }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
- }else { return NULL; }
- }
- /*
- * pipeline: [ command ( | command )* ]
- *
- */
- struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data)
- {
- struct Queue *pipeline;
- pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE);
- if(pipeline->size==0)
- {
- free(pipeline);
- push_parsing_error("pipeline is empty",translation_data);
- return NULL;
- }else
- {
- return get_ast_pipeline(pipeline);
- }
- }
- /*
- * command: id [ string ]
- *
- */
- struct AST_Command* parse_command(struct Translation_Data *translation_data)
- {
- struct token *id;
- struct token *string=NULL;
- if(get_kw(translation_data)==KW_ID)
- {
- id=Queue_Pop(translation_data->tokens);
- if(get_kw(translation_data)==KW_STRING)
- string=Queue_Pop(translation_data->tokens);
- return get_ast_command(id,string);
- }else
- {
- push_parsing_error("expected command id",translation_data);
- return NULL;
- }
- }
- /*
- * starting-on-inner: 'on' id ;
- */
- struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states)
- {
- struct token *hold_id;
- struct AST_State *hold_state;
-
- if(get_and_check(translation_data,KW_ON))
- {
- if(get_kw(translation_data)==KW_ID)
- {
- hold_id=Queue_Pop(translation_data->tokens);
- hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size);
- free(hold_id);
- if(hold_state)
- {
-
- return hold_state;
-
- }else { push_parsing_error("starting state is not defined",translation_data); return NULL; }
- }else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; }
- }else { push_parsing_error("expected 'on'",translation_data); return NULL; }
- }
- struct AST_State* get_ast_state(struct token *id)
- {
- struct AST_State *ret;
-
- ret=malloc(sizeof(struct AST_State));
- ret->type=AST_TYPE_STATE;
- ret->id=id;
-
- return ret;
- }
- struct AST_Event* get_ast_event(struct token *id)
- {
- struct AST_Event *ret;
-
- ret=malloc(sizeof(struct AST_Event));
- ret->type=AST_TYPE_EVENT;
- ret->id=id;
-
- return ret;
- }
- struct AST_States* get_ast_states(struct Queue *states)
- {
- struct AST_States *ret;
- struct AST_State *hold_state;
-
- /*perhaps no states error should be handled here*/
- assert(states && states->size>0);
-
- ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size]));
- ret->type=AST_TYPE_STATES;
- ret->number_of_states=states->size;
- ret->states_map=malloc(sizeof(struct Map));
-
- Map_Init(ret->states_map);
-
- while(states->size>0)
- {
- hold_state=Queue_Pop(states);
- Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state);
- ret->states[states->size]=hold_state;
- }
-
- assert(states->size==0);
- free(states);
-
- return ret;
- }
- struct AST_Events* get_ast_events(struct Queue *events)
- {
- struct AST_Events *ret;
- struct AST_Event *hold_event;
-
- /*perhaps no events error should be handled here*/
- assert(events && events->size>0);
-
- ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size]));
- ret->type=AST_TYPE_EVENTS;
- ret->number_of_events=events->size;
- ret->events_map=malloc(sizeof(struct Map));
-
- Map_Init(ret->events_map);
-
- while(events->size>0)
- {
- hold_event=Queue_Pop(events);
- Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event);
- ret->events[events->size]=hold_event;
- }
-
- assert(events->size==0);
- free(events);
-
- return ret;
- }
- struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline)
- {
- struct AST_Transition *ret;
- ret=malloc(sizeof(struct AST_Transition));
- ret->type=AST_TYPE_TRANSITION;
- ret->from=from;
- ret->to=to;
- ret->event=event;
- ret->pipeline=pipeline;
-
- return ret;
- }
- struct AST_Command* get_ast_command(struct token *function_name,struct token *argument)
- {
- struct AST_Command *ret;
- ret=malloc(sizeof(struct AST_Command));
- ret->type=AST_TYPE_COMMAND;
- ret->function_name=function_name;
- ret->argument=argument;
-
- return ret;
- }
- struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline)
- {
- struct AST_Pipeline *ret;
-
- ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size]));
- ret->type=AST_TYPE_PIPELINE;
- ret->size=pipeline->size;
- pointer_array_fill((void**)ret->pipeline,pipeline);
-
- assert(pipeline->size==0);
- free(pipeline);
-
- return ret;
- }
- struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state)
- {
- struct AST_Machine *ret;
-
- ret=malloc(sizeof(struct AST_Machine));
- ret->type=AST_TYPE_MACHINE;
- ret->id=id;
- ret->states=states;
- ret->events=events;
- ret->transitions=transitions;
-
- return ret;
- }
- struct AST_Transitions* get_ast_transitions(struct Queue *transitions)
- {
- struct AST_Transitions *ret;
- ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size]));
- ret->type=AST_TYPE_TRANSITIONS;
- ret->size=transitions->size;
-
- pointer_array_fill((void**)ret->transitions,transitions);
-
- assert(transitions->size==0);
- free(transitions);
-
- return ret;
- }
- void delete_ast(struct AST* ast)
- {
- switch(ast->type)
- {
- case AST_TYPE_MACHINE:
- delete_ast_machine((struct AST_Machine*)ast);
- break;
- case AST_TYPE_STATE:
- delete_ast_state((struct AST_State*)ast);
- break;
- case AST_TYPE_STATES:
- delete_ast_states((struct AST_States*)ast);
- break;
- case AST_TYPE_EVENT:
- delete_ast_event((struct AST_Event*)ast);
- break;
- case AST_TYPE_EVENTS:
- delete_ast_events((struct AST_Events*)ast);
- break;
- case AST_TYPE_TRANSITION:
- delete_ast_transition((struct AST_Transition*)ast);
- break;
- case AST_TYPE_TRANSITIONS:
- delete_ast_transitions((struct AST_Transitions*)ast);
- break;
- case AST_TYPE_COMMAND:
- delete_ast_command((struct AST_Command*)ast);
- break;
- case AST_TYPE_PIPELINE:
- delete_ast_pipeline((struct AST_Pipeline*)ast);
- break;
- }
- }
- void delete_ast_event(struct AST_Event* ast)
- {
- if(ast==NULL)return;
- delete_token(ast->id);
- free(ast);
- }
- void delete_ast_states(struct AST_States* ast)
- {
- size_t i;
- if(ast==NULL)return;
- for(i=0;i<ast->number_of_states;++i)
- delete_ast_state(ast->states[i]);
- free(ast);
- }
- void delete_ast_events(struct AST_Events* ast)
- {
- size_t i;
- if(ast==NULL)return;
- for(i=0;i<ast->number_of_events;++i)
- delete_ast_event(ast->events[i]);
- free(ast);
- }
- void delete_ast_transition(struct AST_Transition* ast)
- {
- if(ast==NULL)return;
- if(ast->pipeline!=NULL)
- delete_ast_pipeline(ast->pipeline);
- free(ast);
- }
- void delete_ast_command(struct AST_Command* ast)
- {
- if(ast==NULL)return;
- delete_token(ast->function_name);
- if(ast->argument!=NULL)
- delete_token(ast->argument);
- free(ast);
- }
- void delete_ast_pipeline(struct AST_Pipeline* ast)
- {
- size_t i;
- if(ast==NULL)return;
- for(i=0;i<ast->size;++i)
- delete_ast_command(ast->pipeline[i]);
- free(ast);
- }
- void delete_ast_machine(struct AST_Machine* ast)
- {
- if(ast==NULL)return;
- if(ast->id!=NULL)
- delete_token(ast->id);
- if(ast->states!=NULL)
- delete_ast_states(ast->states);
- if(ast->events!=NULL)
- delete_ast_events(ast->events);
- if(ast->transitions!=NULL)
- delete_ast_transitions(ast->transitions);
- }
- void delete_ast_transitions(struct AST_Transitions* ast)
- {
- size_t i;
- if(ast==NULL)return;
- for(i=0;i<ast->size;++i)
- delete_ast_transition(ast->transitions[i]);
- free(ast);
- }
- void delete_ast_state(struct AST_State* ast)
- {
- if(ast==NULL)return;
- if(ast->id!=NULL)
- delete_token(ast->id);
- free(ast);
- }
- void pointer_array_fill(void **array,struct Queue *q)
- {
- size_t i;
- for(i=0;q->size>0;++i)
- array[i]=Queue_Pop(q);
- }
-
- struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim)
- {
- struct Queue *q;
- struct AST* hold_ast;
-
- q=malloc(sizeof(struct Queue));
- Queue_Init(q);
- while(hold_ast=parser(translation_data))
- {
- Queue_Push(q,hold_ast);
- if(!get_and_check(translation_data,delim))
- break;
- }
- return q;
- }
-
- #endif
F diff --git a/parser.h b/parser.h deleted file mode 100644 --- a/parser.h +++ /dev/null
- #ifndef PARSER_H
- #define PARSER_H PARSER_H
- #include <program.h>
- #include <stddef.h>
- #include <assert.h>
- #include <map.h>
-
- enum AST_Type
- {
- AST_TYPE_MACHINE,
- AST_TYPE_STATE,
- AST_TYPE_STATES,
- AST_TYPE_EVENT,
- AST_TYPE_EVENTS,
- AST_TYPE_TRANSITION,
- AST_TYPE_TRANSITIONS,
- AST_TYPE_COMMAND,
- AST_TYPE_PIPELINE,
- };
- struct AST
- {
- enum AST_Type type;
- };
- struct AST_State
- {
- enum AST_Type type;
- struct token *id;
- };
- struct AST_Event
- {
- enum AST_Type type;
- struct token *id;
- };
- struct AST_States
- {
- enum AST_Type type;
- size_t number_of_states;
- struct Map *states_map;
- struct AST_State *states[];
- };
- struct AST_Events
- {
- enum AST_Type type;
- size_t number_of_events;
- struct Map *events_map;
- struct AST_Event *events[];
- };
- struct AST_Transition
- {
- enum AST_Type type;
- struct AST_State *from;
- struct AST_State *to;
- struct AST_Event *event;
- struct AST_Pipeline *pipeline;
- };
- struct AST_Command
- {
- enum AST_Type type;
- struct token *function_name;
- struct token *argument;
- };
- struct AST_Pipeline
- {
- enum AST_Type type;
- size_t size;
- struct AST_Command *pipeline[];
- };
- struct AST_Machine
- {
- enum AST_Type type;
- struct token *id;
- struct AST_States *states;
- struct AST_Events *events;
- struct AST_Transitions *transitions;
- };
- struct AST_Transitions
- {
- enum AST_Type type;
- size_t size;
- struct AST_Transition *transitions[];
- };
-
-
- struct AST* parse_unit(struct Translation_Data *translation_data);
- struct AST_Machine* parse_machine(struct Translation_Data *translation_data);
- struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data);
- struct AST_States* parse_states_inner(struct Translation_Data *translation_data);
- struct AST_State* parse_state(struct Translation_Data *translation_data);
- struct AST_Events* parse_events_inner(struct Translation_Data *translation_data);
- struct AST_Event* parse_event(struct Translation_Data *translation_data);
- struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events );
- struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);
- struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data);
- struct AST_Command* parse_command(struct Translation_Data *translation_data);
- struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states);
-
-
- struct AST_State* get_ast_state(struct token *id);
- struct AST_Event* get_ast_event(struct token *id);
- struct AST_States* get_ast_states(struct Queue *states);
- struct AST_Events* get_ast_events(struct Queue *events);
- struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
- struct AST_Command* get_ast_command(struct token *function_name,struct token *argument);
- struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline);
- struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state);
- struct AST_Transitions* get_ast_transitions(struct Queue *transitions);
-
-
- void delete_ast(struct AST* ast);
- void delete_ast_event(struct AST_Event* ast);
- void delete_ast_states(struct AST_States* ast);
- void delete_ast_state(struct AST_State* ast);
- void delete_ast_events(struct AST_Events* ast);
- void delete_ast_transition(struct AST_Transition* ast);
- void delete_ast_command(struct AST_Command* ast);
- void delete_ast_pipeline(struct AST_Pipeline* ast);
- void delete_ast_machine(struct AST_Machine* ast);
- void delete_ast_transitions(struct AST_Transitions* ast);
-
-
- void pointer_array_fill(void **array,struct Queue *q);
- struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim);
-
- #endif
F diff --git a/print.c b/print.c deleted file mode 100644 --- a/print.c +++ /dev/null
- #ifndef PRINT_C
- #define PRINT_C PRINT_C
- #include<print.h>
-
- void print_keyword_enum(enum Keyword code)
- {
- switch(code)
- {
- case KW_MACHINE:
- printf("KW_MACHINE");
- break;
- case KW_FROM:
- printf("KW_FROM");
- break;
- case KW_TO:
- printf("KW_TO");
- break;
- case KW_ON:
- printf("KW_ON");
- break;
- case KW_ID:
- printf("KW_ID");
- break;
- case KW_STRING:
- printf("KW_STRING");
- break;
- case KW_NOP:
- printf("KW_NOP");
- break;
- case KW_EOF:
- printf("KW_EOF");
- break;
- case KW_OPEN_SQUARE:
- printf("KW_OPEN_SQUARE");
- break;
- case KW_CLOSE_SQUARE:
- printf("KW_CLOSE_SQUARE");
- break;
- case KW_PIPE:
- printf("KW_PIPE");
- break;
- case KW_SEMI_COLUMN:
- printf("KW_SEMI_COLUMN");
- break;
- case KW_STARTING:
- printf("KW_STARTING");
- break;
- case KW_STATES:
- printf("KW_STATES");
- break;
- case KW_EVENTS:
- printf("KW_EVENTS");
- break;
- case KW_EVENT:
- printf("KW_EVENT");
- break;
- case KW_TRANSITIONS:
- printf("KW__TRANSITIONS");
- break;
- case KW_EXECUTE:
- printf("KW_EXECUTE");
- break;
- case KW_COMMA:
- printf("KW_COMMA");
- break;
- default:
- printf("LEXERROR");
- }
- }
- void print_token(struct token *token)
- {
- size_t i;
- assert(token);
-
- printf("[ ");
- print_keyword_enum(token->type);
- printf(" ");
- for(i=0;i<token->size;++i)
- printf("%c",token->data[i]);
- printf(" ] ");
-
- }
- void print_tokens(struct Queue *tokens)
- {
- struct Queue_Node *it;
- assert(tokens);
-
- for(it=tokens->first;it!=NULL;it=it->prev)
- {
- print_token( (struct token*)(it->data));
- printf(" ");
- }
- }
- void print_ast_enum(enum AST_Type type)
- {
- switch(type)
- {
- case AST_TYPE_MACHINE:
- printf("AST_TYPE_MACHINE");
- break;
- case AST_TYPE_STATE:
- printf("AST_TYPE_STATE");
- break;
- case AST_TYPE_STATES:
- printf("AST_TYPE_STATES");
- break;
- case AST_TYPE_EVENT:
- printf("AST_TYPE_EVENT");
- break;
- case AST_TYPE_EVENTS:
- printf("AST_TYPE_EVENTS");
- break;
- case AST_TYPE_TRANSITION:
- printf("AST_TYPE_TRANSITION");
- break;
- case AST_TYPE_TRANSITIONS:
- printf("AST_TYPE_TRANSITIONS");
- break;
- case AST_TYPE_COMMAND:
- printf("AST_TYPE_COMMAND");
- break;
- case AST_TYPE_PIPELINE:
- printf("AST_TYPE_PIPELINE");
- break;
- default:
- printf("AST_NOP");
- }
-
- }
- void print_ast(struct AST *tree)
- {
- assert(tree);
-
- switch(tree->type)
- {
- case AST_TYPE_MACHINE:
- print_ast_machine((struct AST_Machine*)tree);
- break;
- case AST_TYPE_STATE:
- print_ast_state((struct AST_State*)tree);
- break;
- case AST_TYPE_STATES:
- print_ast_states((struct AST_States*)tree);
- break;
- case AST_TYPE_EVENT:
- print_ast_event((struct AST_Event*)tree);
- break;
- case AST_TYPE_EVENTS:
- print_ast_events((struct AST_Events*)tree);
- break;
- case AST_TYPE_TRANSITION:
- print_ast_transition((struct AST_Transition*)tree);
- break;
- case AST_TYPE_TRANSITIONS:
- print_ast_transitions((struct AST_Transitions*)tree);
- break;
- case AST_TYPE_COMMAND:
- print_ast_command((struct AST_Command*)tree);
- break;
- case AST_TYPE_PIPELINE:
- print_ast_pipeline((struct AST_Pipeline*)tree);
- break;
- default:
- printf("noast");
- }
- }
- void print_ast_state(struct AST_State* tree)
- {
- assert(tree);
-
- printf("[ STATE: ");
- print_ast_enum(tree->type);
- printf("]");
- }
- void print_ast_event(struct AST_Event* tree)
- {
- assert(tree);
-
- printf("[ EVENT: ");
- print_ast_enum(tree->type);
- printf("]");
- }
- void print_ast_states(struct AST_States* tree)
- {
- size_t i;
- assert(tree);
-
- printf("STATES [\n");
- for(i=0;i<tree->number_of_states;++i)
- {
- print_ast_state(tree->states[i]);
- printf(" ");
- }
- printf("\n ] END STATES \n");
- }
- void print_ast_events(struct AST_Events* tree)
- {
- size_t i;
- assert(tree);
-
- printf("EVENTS [\n");
- for(i=0;i<tree->number_of_events;++i)
- {
- print_ast_event(tree->events[i]);
- printf(" ");
- }
- printf("\n ] END EVENTS \n");
- }
- void print_ast_transition(struct AST_Transition* tree)
- {
- assert(tree);
-
- printf("TRANSITION [\nFROM");
- print_ast_state(tree->from);
- printf(" TO ");
- print_ast_state(tree->to);
- printf(" COMMAND {");
- if(tree->pipeline==NULL)
- {
- printf("NULL");
- }else
- {
- print_ast_pipeline(tree->pipeline);
- }
-
- }
- void print_ast_command(struct AST_Command* tree)
- {
- assert(tree);
-
- printf("( command ");
- print_token(tree->function_name);
- if(tree->argument==NULL)
- {
- printf(" NOARGUMENTS ");
- }else
- {
- printf(" \"");
- print_token(tree->argument);
- printf("\" ");
- }
- printf(")");
- }
- void print_ast_pipeline(struct AST_Pipeline* tree)
- {
- size_t i;
- assert(tree);
- printf("PIPELINE <");
- for(i=0;i<tree->size;++i)
- {
- print_ast_command(tree->pipeline[i]);
- printf(" | ");
- }
- printf("> PIPELINE_END");
- }
- void print_ast_machine(struct AST_Machine* tree)
- {
- assert(tree);
- printf("MACHINE ");
- print_token(tree->id);
- printf(" [\n");
- print_ast_states(tree->states);
- print_ast_events(tree->events);
- print_ast_transitions(tree->transitions);
- printf("] MACHINE_END\n");
- }
- void print_ast_transitions(struct AST_Transitions* tree)
- {
- size_t i;
- assert(tree);
- printf("TRANSITIONS [\n");
- for(i=0;i<tree->size;++i)
- {
- print_ast_transition(tree->transitions[i]);
- printf("\n");
- }
- printf("] TRANSITIONS_END\n");
- }
- void print_error(struct Error *error)
- {
- assert(error);
- printf("Error: %s, line %ld row %ld\n",error->message,error->row,error->column);
- }
- void print_errors(struct Translation_Data *translation_data)
- {
- struct Queue_Node *it;
- assert(translation_data);
-
- for(it=translation_data->errors->first;it!=NULL;it=it->prev)
- {
- print_error(it->data);
- }
- }
- #endif
F diff --git a/print.h b/print.h deleted file mode 100644 --- a/print.h +++ /dev/null
- #ifndef PRINT_H
- #define PRINT_H PRINT_H
- #include <stdio.h>
- #include <lexer.h>
- #include <parser.h>
- #include <queue.h>
-
-
- void print_keyword_enum(enum Keyword code);
- void print_token(struct token *token);
- void print_tokens(struct Queue *tokens);
-
- void print_ast_enum(enum AST_Type type);
- void print_ast(struct AST *tree);
- void print_ast_state(struct AST_State* tree);
- void print_ast_event(struct AST_Event* tree);
- void print_ast_states(struct AST_States* tree);
- void print_ast_events(struct AST_Events* tree);
- void print_ast_transition(struct AST_Transition* tree);
- void print_ast_command(struct AST_Command* tree);
- void print_ast_pipeline(struct AST_Pipeline* tree);
- void print_ast_machine(struct AST_Machine* tree);
- void print_ast_transitions(struct AST_Transitions* tree);
-
- void print_error(struct Error *error);
- void print_errors(struct Translation_Data *translation_data);
- #endif
F diff --git a/program.c b/program.c deleted file mode 100644 --- a/program.c +++ /dev/null
- #ifndef PROGRAM_C
- #define PROGRAM_C
- #include<program.h>
-
- 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;i<argc;++i)
- {
- if(!strncmp(argv[i],"--print-tokens",sizeof("--print-tokens")))
- ret->target=OPTION_TARGET_TOKENS;
- else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))
- ret->target=OPTION_TARGET_AST;
- else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output")))
- {
- if(++i<argc)
- {
- if(strnlen(argv[i],101)<100)
- ret->src_name=argv[i];
- else if(!ret->is_quiet)
- {
- fprintf(stderr,"Error: Output filename is too long");
- exit(1);
- }else
- {
- exit(1);
- }
- }
- }else if(strnlen(argv[i],101)<100)
- {
- ret->src_name=argv[i];
- }else if(!ret->is_quiet)
- {
- fprintf(stderr,"Error: Input filename is too long");
- exit(1);
- }else
- {
- exit(1);
- }
-
- }
-
- if(ret->target==OPTION_DEFAULT)
- ret->target=OPTION_TARGET_AST;
-
- return ret;
- }
- struct Translation_Data* get_translation_data()
- {
- struct 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
F diff --git a/program.h b/program.h deleted file mode 100644 --- a/program.h +++ /dev/null
- #ifndef PROGRAM_H
- #define PROGRAM_H
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <queue.h>
- #include <lexer.h>
- #include <assert.h>
-
- struct token;
- enum Keyword;
-
- enum Options_Target_Type
- {
- OPTION_TARGET_TOKENS,
- OPTION_TARGET_AST,
- OPTION_DEFAULT,
- };
-
- struct Source
- {
- 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
F diff --git a/queue.c b/queue.c deleted file mode 100644 --- a/queue.c +++ /dev/null
- #ifndef GQUEUE_C
- #define GQUEUE_C GQUEUE_C
- #include<queue.h>
-
-
- 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
F diff --git a/queue.h b/queue.h deleted file mode 100644 --- a/queue.h +++ /dev/null
- #ifndef GQUEUE_H
- #define GQUEUE_H GQUEUE_H
- #include<stdlib.h>
-
-
- 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
F diff --git a/src/backend/print.c b/src/backend/print.c new file mode 100644 --- /dev/null +++ b/src/backend/print.c
+ #ifndef PRINT_C
+ #define PRINT_C PRINT_C
+ #include<print.h>
+
+ void print_keyword_enum(enum Keyword code)
+ {
+ switch(code)
+ {
+ case KW_MACHINE:
+ printf("KW_MACHINE");
+ break;
+ case KW_FROM:
+ printf("KW_FROM");
+ break;
+ case KW_TO:
+ printf("KW_TO");
+ break;
+ case KW_ON:
+ printf("KW_ON");
+ break;
+ case KW_ID:
+ printf("KW_ID");
+ break;
+ case KW_STRING:
+ printf("KW_STRING");
+ break;
+ case KW_NOP:
+ printf("KW_NOP");
+ break;
+ case KW_EOF:
+ printf("KW_EOF");
+ break;
+ case KW_OPEN_SQUARE:
+ printf("KW_OPEN_SQUARE");
+ break;
+ case KW_CLOSE_SQUARE:
+ printf("KW_CLOSE_SQUARE");
+ break;
+ case KW_PIPE:
+ printf("KW_PIPE");
+ break;
+ case KW_SEMI_COLUMN:
+ printf("KW_SEMI_COLUMN");
+ break;
+ case KW_STARTING:
+ printf("KW_STARTING");
+ break;
+ case KW_STATES:
+ printf("KW_STATES");
+ break;
+ case KW_EVENTS:
+ printf("KW_EVENTS");
+ break;
+ case KW_EVENT:
+ printf("KW_EVENT");
+ break;
+ case KW_TRANSITIONS:
+ printf("KW__TRANSITIONS");
+ break;
+ case KW_EXECUTE:
+ printf("KW_EXECUTE");
+ break;
+ case KW_COMMA:
+ printf("KW_COMMA");
+ break;
+ default:
+ printf("LEXERROR");
+ }
+ }
+ void print_token(struct token *token)
+ {
+ size_t i;
+ assert(token);
+
+ printf("[ ");
+ print_keyword_enum(token->type);
+ printf(" ");
+ for(i=0;i<token->size;++i)
+ printf("%c",token->data[i]);
+ printf(" ] ");
+
+ }
+ void print_tokens(struct Queue *tokens)
+ {
+ struct Queue_Node *it;
+ assert(tokens);
+
+ for(it=tokens->first;it!=NULL;it=it->prev)
+ {
+ print_token( (struct token*)(it->data));
+ printf(" ");
+ }
+ }
+ void print_ast_enum(enum AST_Type type)
+ {
+ switch(type)
+ {
+ case AST_TYPE_MACHINE:
+ printf("AST_TYPE_MACHINE");
+ break;
+ case AST_TYPE_STATE:
+ printf("AST_TYPE_STATE");
+ break;
+ case AST_TYPE_STATES:
+ printf("AST_TYPE_STATES");
+ break;
+ case AST_TYPE_EVENT:
+ printf("AST_TYPE_EVENT");
+ break;
+ case AST_TYPE_EVENTS:
+ printf("AST_TYPE_EVENTS");
+ break;
+ case AST_TYPE_TRANSITION:
+ printf("AST_TYPE_TRANSITION");
+ break;
+ case AST_TYPE_TRANSITIONS:
+ printf("AST_TYPE_TRANSITIONS");
+ break;
+ case AST_TYPE_COMMAND:
+ printf("AST_TYPE_COMMAND");
+ break;
+ case AST_TYPE_PIPELINE:
+ printf("AST_TYPE_PIPELINE");
+ break;
+ default:
+ printf("AST_NOP");
+ }
+
+ }
+ void print_ast(struct AST *tree)
+ {
+ assert(tree);
+
+ switch(tree->type)
+ {
+ case AST_TYPE_MACHINE:
+ print_ast_machine((struct AST_Machine*)tree);
+ break;
+ case AST_TYPE_STATE:
+ print_ast_state((struct AST_State*)tree);
+ break;
+ case AST_TYPE_STATES:
+ print_ast_states((struct AST_States*)tree);
+ break;
+ case AST_TYPE_EVENT:
+ print_ast_event((struct AST_Event*)tree);
+ break;
+ case AST_TYPE_EVENTS:
+ print_ast_events((struct AST_Events*)tree);
+ break;
+ case AST_TYPE_TRANSITION:
+ print_ast_transition((struct AST_Transition*)tree);
+ break;
+ case AST_TYPE_TRANSITIONS:
+ print_ast_transitions((struct AST_Transitions*)tree);
+ break;
+ case AST_TYPE_COMMAND:
+ print_ast_command((struct AST_Command*)tree);
+ break;
+ case AST_TYPE_PIPELINE:
+ print_ast_pipeline((struct AST_Pipeline*)tree);
+ break;
+ default:
+ printf("noast");
+ }
+ }
+ void print_ast_state(struct AST_State* tree)
+ {
+ assert(tree);
+
+ printf("[ STATE: ");
+ print_ast_enum(tree->type);
+ printf("]");
+ }
+ void print_ast_event(struct AST_Event* tree)
+ {
+ assert(tree);
+
+ printf("[ EVENT: ");
+ print_ast_enum(tree->type);
+ printf("]");
+ }
+ void print_ast_states(struct AST_States* tree)
+ {
+ size_t i;
+ assert(tree);
+
+ printf("STATES [\n");
+ for(i=0;i<tree->number_of_states;++i)
+ {
+ print_ast_state(tree->states[i]);
+ printf(" ");
+ }
+ printf("\n ] END STATES \n");
+ }
+ void print_ast_events(struct AST_Events* tree)
+ {
+ size_t i;
+ assert(tree);
+
+ printf("EVENTS [\n");
+ for(i=0;i<tree->number_of_events;++i)
+ {
+ print_ast_event(tree->events[i]);
+ printf(" ");
+ }
+ printf("\n ] END EVENTS \n");
+ }
+ void print_ast_transition(struct AST_Transition* tree)
+ {
+ assert(tree);
+
+ printf("TRANSITION [\nFROM");
+ print_ast_state(tree->from);
+ printf(" TO ");
+ print_ast_state(tree->to);
+ printf(" COMMAND {");
+ if(tree->pipeline==NULL)
+ {
+ printf("NULL");
+ }else
+ {
+ print_ast_pipeline(tree->pipeline);
+ }
+
+ }
+ void print_ast_command(struct AST_Command* tree)
+ {
+ assert(tree);
+
+ printf("( command ");
+ print_token(tree->function_name);
+ if(tree->argument==NULL)
+ {
+ printf(" NOARGUMENTS ");
+ }else
+ {
+ printf(" \"");
+ print_token(tree->argument);
+ printf("\" ");
+ }
+ printf(")");
+ }
+ void print_ast_pipeline(struct AST_Pipeline* tree)
+ {
+ size_t i;
+ assert(tree);
+ printf("PIPELINE <");
+ for(i=0;i<tree->size;++i)
+ {
+ print_ast_command(tree->pipeline[i]);
+ printf(" | ");
+ }
+ printf("> PIPELINE_END");
+ }
+ void print_ast_machine(struct AST_Machine* tree)
+ {
+ assert(tree);
+ printf("MACHINE ");
+ print_token(tree->id);
+ printf(" [\n");
+ print_ast_states(tree->states);
+ print_ast_events(tree->events);
+ print_ast_transitions(tree->transitions);
+ printf("] MACHINE_END\n");
+ }
+ void print_ast_transitions(struct AST_Transitions* tree)
+ {
+ size_t i;
+ assert(tree);
+ printf("TRANSITIONS [\n");
+ for(i=0;i<tree->size;++i)
+ {
+ print_ast_transition(tree->transitions[i]);
+ printf("\n");
+ }
+ printf("] TRANSITIONS_END\n");
+ }
+ void print_error(struct Error *error)
+ {
+ assert(error);
+ printf("Error: %s, line %ld row %ld\n",error->message,error->row,error->column);
+ }
+ void print_errors(struct Translation_Data *translation_data)
+ {
+ struct Queue_Node *it;
+ assert(translation_data);
+
+ for(it=translation_data->errors->first;it!=NULL;it=it->prev)
+ {
+ print_error(it->data);
+ }
+ }
+ #endif
F diff --git a/src/backend/print.h b/src/backend/print.h new file mode 100644 --- /dev/null +++ b/src/backend/print.h
+ #ifndef PRINT_H
+ #define PRINT_H PRINT_H
+ #include <stdio.h>
+ #include <lexer.h>
+ #include <parser.h>
+ #include <queue.h>
+
+
+ void print_keyword_enum(enum Keyword code);
+ void print_token(struct token *token);
+ void print_tokens(struct Queue *tokens);
+
+ void print_ast_enum(enum AST_Type type);
+ void print_ast(struct AST *tree);
+ void print_ast_state(struct AST_State* tree);
+ void print_ast_event(struct AST_Event* tree);
+ void print_ast_states(struct AST_States* tree);
+ void print_ast_events(struct AST_Events* tree);
+ void print_ast_transition(struct AST_Transition* tree);
+ void print_ast_command(struct AST_Command* tree);
+ void print_ast_pipeline(struct AST_Pipeline* tree);
+ void print_ast_machine(struct AST_Machine* tree);
+ void print_ast_transitions(struct AST_Transitions* tree);
+
+ void print_error(struct Error *error);
+ void print_errors(struct Translation_Data *translation_data);
+ #endif
F diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c new file mode 100644 --- /dev/null +++ b/src/frontend/lexer.c
+ #ifndef LEXER_C
+ #define LEXER_C
+ #include <lexer.h>
+
+ #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_src<src->src_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;i<word_size && word[i]==src->src[src->where_in_src+i];++i);
+
+ if(i<word_size)
+ {
+ return 0;
+ }
+ else if( (needs_space_after && isspace(src->src[src->where_in_src+i])) || !needs_space_after )
+ {
+ src->where_in_src+=i;
+ src->current_column+=i;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ void skip_white_space(struct Source *src)
+ {
+ while(src->where_in_src<src->src_size && isspace(src->src[src->where_in_src]))
+ {
+ if(src->src[src->where_in_src]=='\n')
+ {
+ ++src->current_row;
+ src->current_column=0;
+ }
+ ++src->where_in_src;
+ }
+ }
+
+ void push_token_into_map(struct token *token,struct Map *map,void *thing)
+ {
+ Map_Push(map,token->data,token->size,thing);
+ }
+ #endif
F diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h new file mode 100644 --- /dev/null +++ b/src/frontend/lexer.h
+ #ifndef LEXER_H
+ #define LEXER_H
+ #include <ctype.h> //isspace
+ #include <program.h>
+ #include <queue.h>
+ #include <map.h>
+
+ struct Translation_Data;
+ struct Source;
+
+ enum Keyword
+ {
+ KW_MACHINE,
+ KW_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
F diff --git a/src/frontend/parser.c b/src/frontend/parser.c new file mode 100644 --- /dev/null +++ b/src/frontend/parser.c
+ #ifndef PARSER_C
+ #define PARSER_C PARSER_C
+ #include <parser.h>
+
+ /*
+ * parse-unit: machine
+ *
+ */
+ struct AST* parse_unit(struct Translation_Data *translation_data)
+ {
+ return (struct AST*)parse_machine(translation_data);
+ }
+ /*
+ * machine: 'machine' id '[' machine-inner ']' ';'
+ *
+ */
+ struct AST_Machine* parse_machine(struct Translation_Data *translation_data)
+ {
+ struct AST_Machine *ret;
+ struct token *hold_id;
+ if(get_and_check(translation_data,KW_MACHINE))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id=Queue_Pop(translation_data->tokens);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data);
+ if(has_new_errors(translation_data))
+ {
+ delete_ast_machine(ret);
+ touch_errors(translation_data);
+
+ return NULL;
+ }
+ if(get_and_check(translation_data,KW_CLOSE_SQUARE))
+ {
+ if(get_and_check(translation_data,KW_SEMI_COLUMN))
+ return ret;
+ else
+ {
+ push_parsing_error("';' expected after machine definition",translation_data);
+ delete_ast_machine(ret);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("closing ']' expected",translation_data);
+ delete_ast_machine(ret);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("opening '[' expected",translation_data);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("expected a name for the machine",translation_data);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("'machine' expected",translation_data);
+ return NULL;
+ }
+ }
+ /*
+ * machine-inner : 'states' '[' states-inner ']' ';'
+ * 'events' '[' events-inner ']' ';'
+ * 'transitions' '[' transitions-inner ']' ';'
+ * 'starting' start-on-inner ';'
+ */
+ struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data)
+ {
+ struct AST_States *states=NULL;
+ struct AST_Events *events=NULL;
+ struct AST_Transitions *transitions=NULL;
+ struct AST_State *starting_state=NULL;
+ unsigned char i;
+ for(i=0;i<4;++i)
+ switch(get_kw(translation_data))
+ {
+ case KW_STATES:
+ if(states)
+ {
+ push_parsing_error("defining two sets of states",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ states=parse_states_inner(translation_data);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of states definition",translation_data);
+ goto error_cleanup;
+ }
+
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_TRANSITIONS:
+ if(states==NULL && events==NULL)
+ {
+ push_parsing_error("defining transitions before states and events",translation_data);
+ goto error_cleanup;
+ }else if(transitions)
+ {
+ push_parsing_error("defining two sets of transitions",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ transitions=parse_transitions_inner(translation_data,states,events);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of transitions definition",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_EVENTS:
+ if(events)
+ {
+ push_parsing_error("defining two sets of transitions",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ events=parse_events_inner(translation_data);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of events definition",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_STARTING:
+ chomp(translation_data);
+ if(!starting_state)
+ {
+ if(states)
+ {
+ starting_state=parse_start_on(translation_data,states);
+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ';' at end "
+ "of starting state declaration",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("states need to be defined"
+ " before defining a starting one",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("starting state is defined",translation_data);
+ goto error_cleanup;
+ }
+ break;
+ default:
+ push_parsing_error("expected states transitions or events",translation_data);
+ goto error_cleanup;
+
+ }
+
+ return get_ast_machine(machine_id,states,events,transitions,starting_state);
+
+ error_cleanup:
+ push_parsing_error("in machine",translation_data);
+ if(states)delete_ast_states(states);
+ if(events)delete_ast_events(events);
+ if(transitions)delete_ast_transitions(transitions);
+ return NULL;
+ }
+ /*
+ * states-inner: state (, state)*
+ *
+ */
+ struct AST_States* parse_states_inner(struct Translation_Data *translation_data)
+ {
+ struct Queue *ids;
+ struct AST_State *hold_state;
+
+ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA);
+ if(ids->size==0)
+ {
+ push_parsing_error("there needs to be atleast one state",translation_data);
+ free(ids);
+ return NULL;
+ }else
+ {
+
+ return get_ast_states(ids);
+ }
+ }
+ /*
+ * state : id
+ *
+ */
+ struct AST_State* parse_state(struct Translation_Data *translation_data)
+ {
+ if(get_kw(translation_data)==KW_ID)
+ return get_ast_state(Queue_Pop(translation_data->tokens));
+ else
+ return NULL;
+ }
+ /*
+ * events-inner: id (, id)*
+ *
+ */
+ struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)
+ {
+ struct Queue *ids;
+ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA);
+ if(ids->size==0)
+ {
+ push_parsing_error("there needs to be atleast one event",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_events(ids);
+ }
+ }
+ struct AST_Event* parse_event(struct Translation_Data *translation_data)
+ {
+ if(get_kw(translation_data)==KW_ID)
+ return get_ast_event(Queue_Pop(translation_data->tokens));
+ else
+ return NULL;
+ }
+ /*
+ * transitions-inner: ( transition ;)*
+ */
+ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+ {
+ struct Queue *transitions;
+ struct AST_Transition *hold_transition;
+
+ transitions=malloc(sizeof(struct Queue));
+ Queue_Init(transitions);
+
+ while((hold_transition=parse_transition(translation_data,states,events))!=NULL)
+ {
+ Queue_Push(transitions,hold_transition);
+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))
+ break;
+ }
+
+ if(transitions->size==0)
+ {
+ push_parsing_error("there are no transitions",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_transitions(transitions);
+ }
+ }
+ /*
+ * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ]
+ *
+ */
+ struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+ {
+ struct AST_Transition *ret;
+ struct AST_State *hold_from;
+ struct AST_State *hold_to;
+ struct AST_Event *hold_event;
+ struct AST_Pipeline *hold_pipeline=NULL;
+ struct token *hold_token;
+
+ if(get_and_check(translation_data,KW_FROM))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_from!=NULL)
+ {
+ if(get_and_check(translation_data,KW_TO))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_to!=NULL)
+ {
+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_event!=NULL)
+ {
+ if(get_and_check(translation_data,KW_EXECUTE))
+ if((hold_pipeline=parse_pipeline(translation_data))==NULL)
+ { push_parsing_error("after execute",translation_data); return NULL; }
+ /*GOAL*/
+ return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
+ }else { push_parsing_error("event not defined",translation_data); return NULL; }
+ }else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'on event'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined to state in transition",translation_data); }
+ }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'to'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
+ }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ }else { return NULL; }
+ }
+ /*
+ * pipeline: [ command ( | command )* ]
+ *
+ */
+ struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data)
+ {
+ struct Queue *pipeline;
+ pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE);
+ if(pipeline->size==0)
+ {
+ free(pipeline);
+ push_parsing_error("pipeline is empty",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_pipeline(pipeline);
+ }
+ }
+ /*
+ * command: id [ string ]
+ *
+ */
+ struct AST_Command* parse_command(struct Translation_Data *translation_data)
+ {
+ struct token *id;
+ struct token *string=NULL;
+ if(get_kw(translation_data)==KW_ID)
+ {
+ id=Queue_Pop(translation_data->tokens);
+ if(get_kw(translation_data)==KW_STRING)
+ string=Queue_Pop(translation_data->tokens);
+ return get_ast_command(id,string);
+ }else
+ {
+ push_parsing_error("expected command id",translation_data);
+ return NULL;
+ }
+ }
+ /*
+ * starting-on-inner: 'on' id ;
+ */
+ struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states)
+ {
+ struct token *hold_id;
+ struct AST_State *hold_state;
+
+ if(get_and_check(translation_data,KW_ON))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id=Queue_Pop(translation_data->tokens);
+ hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size);
+ free(hold_id);
+ if(hold_state)
+ {
+
+ return hold_state;
+
+ }else { push_parsing_error("starting state is not defined",translation_data); return NULL; }
+ }else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'on'",translation_data); return NULL; }
+ }
+ struct AST_State* get_ast_state(struct token *id)
+ {
+ struct AST_State *ret;
+
+ ret=malloc(sizeof(struct AST_State));
+ ret->type=AST_TYPE_STATE;
+ ret->id=id;
+
+ return ret;
+ }
+ struct AST_Event* get_ast_event(struct token *id)
+ {
+ struct AST_Event *ret;
+
+ ret=malloc(sizeof(struct AST_Event));
+ ret->type=AST_TYPE_EVENT;
+ ret->id=id;
+
+ return ret;
+ }
+ struct AST_States* get_ast_states(struct Queue *states)
+ {
+ struct AST_States *ret;
+ struct AST_State *hold_state;
+
+ /*perhaps no states error should be handled here*/
+ assert(states && states->size>0);
+
+ ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size]));
+ ret->type=AST_TYPE_STATES;
+ ret->number_of_states=states->size;
+ ret->states_map=malloc(sizeof(struct Map));
+
+ Map_Init(ret->states_map);
+
+ while(states->size>0)
+ {
+ hold_state=Queue_Pop(states);
+ Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state);
+ ret->states[states->size]=hold_state;
+ }
+
+ assert(states->size==0);
+ free(states);
+
+ return ret;
+ }
+ struct AST_Events* get_ast_events(struct Queue *events)
+ {
+ struct AST_Events *ret;
+ struct AST_Event *hold_event;
+
+ /*perhaps no events error should be handled here*/
+ assert(events && events->size>0);
+
+ ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size]));
+ ret->type=AST_TYPE_EVENTS;
+ ret->number_of_events=events->size;
+ ret->events_map=malloc(sizeof(struct Map));
+
+ Map_Init(ret->events_map);
+
+ while(events->size>0)
+ {
+ hold_event=Queue_Pop(events);
+ Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event);
+ ret->events[events->size]=hold_event;
+ }
+
+ assert(events->size==0);
+ free(events);
+
+ return ret;
+ }
+ struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline)
+ {
+ struct AST_Transition *ret;
+ ret=malloc(sizeof(struct AST_Transition));
+ ret->type=AST_TYPE_TRANSITION;
+ ret->from=from;
+ ret->to=to;
+ ret->event=event;
+ ret->pipeline=pipeline;
+
+ return ret;
+ }
+ struct AST_Command* get_ast_command(struct token *function_name,struct token *argument)
+ {
+ struct AST_Command *ret;
+ ret=malloc(sizeof(struct AST_Command));
+ ret->type=AST_TYPE_COMMAND;
+ ret->function_name=function_name;
+ ret->argument=argument;
+
+ return ret;
+ }
+ struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline)
+ {
+ struct AST_Pipeline *ret;
+
+ ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size]));
+ ret->type=AST_TYPE_PIPELINE;
+ ret->size=pipeline->size;
+ pointer_array_fill((void**)ret->pipeline,pipeline);
+
+ assert(pipeline->size==0);
+ free(pipeline);
+
+ return ret;
+ }
+ struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state)
+ {
+ struct AST_Machine *ret;
+
+ ret=malloc(sizeof(struct AST_Machine));
+ ret->type=AST_TYPE_MACHINE;
+ ret->id=id;
+ ret->states=states;
+ ret->events=events;
+ ret->transitions=transitions;
+
+ return ret;
+ }
+ struct AST_Transitions* get_ast_transitions(struct Queue *transitions)
+ {
+ struct AST_Transitions *ret;
+ ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size]));
+ ret->type=AST_TYPE_TRANSITIONS;
+ ret->size=transitions->size;
+
+ pointer_array_fill((void**)ret->transitions,transitions);
+
+ assert(transitions->size==0);
+ free(transitions);
+
+ return ret;
+ }
+ void delete_ast(struct AST* ast)
+ {
+ switch(ast->type)
+ {
+ case AST_TYPE_MACHINE:
+ delete_ast_machine((struct AST_Machine*)ast);
+ break;
+ case AST_TYPE_STATE:
+ delete_ast_state((struct AST_State*)ast);
+ break;
+ case AST_TYPE_STATES:
+ delete_ast_states((struct AST_States*)ast);
+ break;
+ case AST_TYPE_EVENT:
+ delete_ast_event((struct AST_Event*)ast);
+ break;
+ case AST_TYPE_EVENTS:
+ delete_ast_events((struct AST_Events*)ast);
+ break;
+ case AST_TYPE_TRANSITION:
+ delete_ast_transition((struct AST_Transition*)ast);
+ break;
+ case AST_TYPE_TRANSITIONS:
+ delete_ast_transitions((struct AST_Transitions*)ast);
+ break;
+ case AST_TYPE_COMMAND:
+ delete_ast_command((struct AST_Command*)ast);
+ break;
+ case AST_TYPE_PIPELINE:
+ delete_ast_pipeline((struct AST_Pipeline*)ast);
+ break;
+ }
+ }
+ void delete_ast_event(struct AST_Event* ast)
+ {
+ if(ast==NULL)return;
+ delete_token(ast->id);
+ free(ast);
+ }
+ void delete_ast_states(struct AST_States* ast)
+ {
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->number_of_states;++i)
+ delete_ast_state(ast->states[i]);
+ free(ast);
+ }
+ void delete_ast_events(struct AST_Events* ast)
+ {
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->number_of_events;++i)
+ delete_ast_event(ast->events[i]);
+ free(ast);
+ }
+ void delete_ast_transition(struct AST_Transition* ast)
+ {
+ if(ast==NULL)return;
+ if(ast->pipeline!=NULL)
+ delete_ast_pipeline(ast->pipeline);
+ free(ast);
+ }
+ void delete_ast_command(struct AST_Command* ast)
+ {
+ if(ast==NULL)return;
+ delete_token(ast->function_name);
+ if(ast->argument!=NULL)
+ delete_token(ast->argument);
+ free(ast);
+ }
+ void delete_ast_pipeline(struct AST_Pipeline* ast)
+ {
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->size;++i)
+ delete_ast_command(ast->pipeline[i]);
+ free(ast);
+ }
+ void delete_ast_machine(struct AST_Machine* ast)
+ {
+ if(ast==NULL)return;
+ if(ast->id!=NULL)
+ delete_token(ast->id);
+ if(ast->states!=NULL)
+ delete_ast_states(ast->states);
+ if(ast->events!=NULL)
+ delete_ast_events(ast->events);
+ if(ast->transitions!=NULL)
+ delete_ast_transitions(ast->transitions);
+ }
+ void delete_ast_transitions(struct AST_Transitions* ast)
+ {
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->size;++i)
+ delete_ast_transition(ast->transitions[i]);
+ free(ast);
+ }
+ void delete_ast_state(struct AST_State* ast)
+ {
+ if(ast==NULL)return;
+ if(ast->id!=NULL)
+ delete_token(ast->id);
+ free(ast);
+ }
+ void pointer_array_fill(void **array,struct Queue *q)
+ {
+ size_t i;
+ for(i=0;q->size>0;++i)
+ array[i]=Queue_Pop(q);
+ }
+
+ struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim)
+ {
+ struct Queue *q;
+ struct AST* hold_ast;
+
+ q=malloc(sizeof(struct Queue));
+ Queue_Init(q);
+ while(hold_ast=parser(translation_data))
+ {
+ Queue_Push(q,hold_ast);
+ if(!get_and_check(translation_data,delim))
+ break;
+ }
+ return q;
+ }
+
+ #endif
F diff --git a/src/frontend/parser.h b/src/frontend/parser.h new file mode 100644 --- /dev/null +++ b/src/frontend/parser.h
+ #ifndef PARSER_H
+ #define PARSER_H PARSER_H
+ #include <program.h>
+ #include <stddef.h>
+ #include <assert.h>
+ #include <map.h>
+
+ enum AST_Type
+ {
+ AST_TYPE_MACHINE,
+ AST_TYPE_STATE,
+ AST_TYPE_STATES,
+ AST_TYPE_EVENT,
+ AST_TYPE_EVENTS,
+ AST_TYPE_TRANSITION,
+ AST_TYPE_TRANSITIONS,
+ AST_TYPE_COMMAND,
+ AST_TYPE_PIPELINE,
+ };
+ struct AST
+ {
+ enum AST_Type type;
+ };
+ struct AST_State
+ {
+ enum AST_Type type;
+ struct token *id;
+ };
+ struct AST_Event
+ {
+ enum AST_Type type;
+ struct token *id;
+ };
+ struct AST_States
+ {
+ enum AST_Type type;
+ size_t number_of_states;
+ struct Map *states_map;
+ struct AST_State *states[];
+ };
+ struct AST_Events
+ {
+ enum AST_Type type;
+ size_t number_of_events;
+ struct Map *events_map;
+ struct AST_Event *events[];
+ };
+ struct AST_Transition
+ {
+ enum AST_Type type;
+ struct AST_State *from;
+ struct AST_State *to;
+ struct AST_Event *event;
+ struct AST_Pipeline *pipeline;
+ };
+ struct AST_Command
+ {
+ enum AST_Type type;
+ struct token *function_name;
+ struct token *argument;
+ };
+ struct AST_Pipeline
+ {
+ enum AST_Type type;
+ size_t size;
+ struct AST_Command *pipeline[];
+ };
+ struct AST_Machine
+ {
+ enum AST_Type type;
+ struct token *id;
+ struct AST_States *states;
+ struct AST_Events *events;
+ struct AST_Transitions *transitions;
+ };
+ struct AST_Transitions
+ {
+ enum AST_Type type;
+ size_t size;
+ struct AST_Transition *transitions[];
+ };
+
+
+ struct AST* parse_unit(struct Translation_Data *translation_data);
+ struct AST_Machine* parse_machine(struct Translation_Data *translation_data);
+ struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data);
+ struct AST_States* parse_states_inner(struct Translation_Data *translation_data);
+ struct AST_State* parse_state(struct Translation_Data *translation_data);
+ struct AST_Events* parse_events_inner(struct Translation_Data *translation_data);
+ struct AST_Event* parse_event(struct Translation_Data *translation_data);
+ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events );
+ struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);
+ struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data);
+ struct AST_Command* parse_command(struct Translation_Data *translation_data);
+ struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states);
+
+
+ struct AST_State* get_ast_state(struct token *id);
+ struct AST_Event* get_ast_event(struct token *id);
+ struct AST_States* get_ast_states(struct Queue *states);
+ struct AST_Events* get_ast_events(struct Queue *events);
+ struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
+ struct AST_Command* get_ast_command(struct token *function_name,struct token *argument);
+ struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline);
+ struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state);
+ struct AST_Transitions* get_ast_transitions(struct Queue *transitions);
+
+
+ void delete_ast(struct AST* ast);
+ void delete_ast_event(struct AST_Event* ast);
+ void delete_ast_states(struct AST_States* ast);
+ void delete_ast_state(struct AST_State* ast);
+ void delete_ast_events(struct AST_Events* ast);
+ void delete_ast_transition(struct AST_Transition* ast);
+ void delete_ast_command(struct AST_Command* ast);
+ void delete_ast_pipeline(struct AST_Pipeline* ast);
+ void delete_ast_machine(struct AST_Machine* ast);
+ void delete_ast_transitions(struct AST_Transitions* ast);
+
+
+ void pointer_array_fill(void **array,struct Queue *q);
+ struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim);
+
+ #endif
F diff --git a/src/main.c b/src/main.c new file mode 100644 --- /dev/null +++ b/src/main.c
+ #include <stdio.h>
+ #include <program.h>
+ #include <lexer.h>
+ #include <string.h>
+ #include <parser.h>
+ #include <print.h>
+
+
+
+ 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;
+ }
F diff --git a/src/misc/map.c b/src/misc/map.c new file mode 100644 --- /dev/null +++ b/src/misc/map.c
+ #ifndef GMAP_C
+ #define GMAP_C GMAP_C
+ #include <map.h>
+
+
+
+ /*
+ * ID and residue and all of delta is assigned to NULL
+ * */
+ void Map_Init(Map *tree)
+ {
+ tree->is_final=0;
+ for(int i=0;i<256;++i)tree->delta[i] = NULL;
+ tree->ID = NULL;
+ }
+
+ void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node)
+ {
+ for(
+ *where=0,*final_node=tree;
+ *where<size && final_node[0]->delta[((unsigned char*)str)[ where[0] ]]!=NULL;
+ ++where[0]
+ )
+ {
+ (*final_node) = (*final_node)->delta[((unsigned char*)str)[*where]];
+ }
+ }
+
+
+
+ /*
+ * tree must not be null
+ * */
+ void Map_Push(Map *tree,void *str,size_t size,void *id)
+ {
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ assert(tree->ID==NULL);
+ tree->ID=id;
+ tree->is_final=1;
+ return;
+ }
+ for(temp;temp<size;++temp)
+ {
+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
+ /*
+ Map_Init(
+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
+ );
+ */
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+
+ }
+
+
+ /*
+ * scours the tree and returns the id of the node that recognises the str
+ * returns NULL if the string is not recognised
+ * */
+ void* Map_Check(Map *tree, void *str,size_t size)
+ {
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp<size)
+ {
+ return NULL;
+ }else
+ {
+ return tree->ID; //this has been set to be the last reached node
+ }
+ }
+
+ void Map_Remove(Map *tree, void *str,size_t size)
+ {
+ Stack stk;
+ Stack_Init(&stk);
+ size_t where;
+ char what_to_null=((char*)str)[0];
+
+ Stack_Push(&stk,tree);
+
+ for(where=0;where<size-1 && tree->delta[((unsigned char*)str)[where]]!=NULL;++where)
+ {
+ tree = tree->delta[((unsigned char*)str)[where]];
+ if(tree->is_final==1)
+ {
+ while(stk.size>0)Stack_Pop(&stk);
+ what_to_null=((char*)str)[where+1];
+ }
+ Stack_Push(&stk,tree);
+ }
+ if(tree->delta[((unsigned char*)str)[where]] == NULL)return;
+ free(tree->delta[((unsigned char*)str)[where]]);
+ while(stk.size>1)free(Stack_Pop(&stk));
+ tree=(Map*)Stack_Pop(&stk);
+ tree->delta[(unsigned char)what_to_null]=NULL;
+
+ }
+ /*This function especially requires that the map has no loops*/
+ void Map_Map(Map *tree,void (*map)(void*))
+ {
+ if(tree->is_final==1)map(tree->ID);
+ for(int i=0;i<256;++i)
+ {
+ if(tree->delta[i]!=NULL)
+ {
+ Map_Map(tree->delta[i],map);
+ }
+ }
+ }
+
+ /*first argument of map is the node id , the second is pass_data*/
+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data)
+ {
+ if(tree->is_final==1)map(tree->ID,pass_data);
+ for(int i=0;i<256;++i)
+ {
+ if(tree->delta[i]!=NULL)
+ {
+ Map_Map_Extended(tree->delta[i],map,pass_data);
+ }
+ }
+ }
+
+
+ /*this does not destroy(free) any memory pointed to by a node in the Map. This does not free() the root (Map *tree) */
+ /*This function especially does not require that the map has no loop ( for example after grepification )*/
+ void Map_Destroy(Map *tree)
+ {
+ Stack path;
+ Stack nodes;
+ Map *current_node;
+ unsigned int i;
+
+
+ Stack_Init(&path);
+ Stack_Init(&nodes);
+
+ Stack_Push(&path,tree);
+ Stack_Push(&nodes,tree);
+
+ /*
+ using DFS we fill up the nodes stack with all the used
+ (accessible) nodes.
+ */
+ while(path.size>0)
+ {
+ current_node=Stack_Pop(&path);
+ current_node->ID=&(current_node->ID);/*mark the node*/
+ for(i=0;i<256;++i)
+ {
+ if(current_node->delta[i]!=NULL && current_node->delta[i]->ID != &(current_node->delta[i]->ID) )
+ {
+ Stack_Push(&path,current_node->delta[i]);
+
+
+ /*we mark the unmarked child of the current_node*/
+ current_node->delta[i]->ID=&(current_node->delta[i]->ID);
+ /*every node in nodes continues to be marked*/
+ Stack_Push(&nodes,current_node->delta[i]);
+ }
+ }
+
+ }
+ /*
+ There should not be any duplicates in here
+ */
+ while(nodes.size>1)
+ {
+ current_node=Stack_Pop(&nodes);
+ /*Again the things that ID points to is not freed ( this structure is used to map the structure of data )
+ deletion of it is up to you.
+ */
+ free(current_node);
+ }
+ /*this is where the root is at- we don't delete it , but we must free the last stack node*/
+ Stack_Pop(&nodes);
+
+
+ }
+
+ /*requres that cpy has no loops*/
+ Map* Map_Copy(Map *cpy)
+ {
+ short i;
+ Map *ret;
+
+ if(cpy==NULL)
+ {
+ return NULL;
+ }
+
+ ret=malloc(sizeof(Map));
+ ret->is_final=cpy->is_final;
+ ret->ID=cpy->ID;
+
+ for(i=0;i<256;++i)
+ {
+ ret->delta[i]=Map_Copy(cpy->delta[i]);
+ }
+ return ret;
+ }
+
+ struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size)
+ {
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp<size)
+ {
+ return NULL;
+ }else
+ {
+ return tree;
+ }
+ }
+
+ struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id)
+ {
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ if(tree->ID!=NULL)tree->ID=id;
+ tree->is_final=1;
+ return tree;
+ }
+
+ for(temp;temp<size;++temp)
+ {
+ Map_Init(
+ tree=
+ tree->delta[((unsigned char*)str)[temp]]=
+ malloc(sizeof(Map))
+ );
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+ return tree;
+ }
+
+ void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id)
+ {
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ if(!tree->is_final)
+ {
+ tree->ID=id;
+ tree->is_final=1;
+ }
+ return tree->ID;
+ }
+ for(temp;temp<size;++temp)
+ {
+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
+ /*
+ Map_Init(
+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
+ );
+ */
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+ return NULL;
+ }
+ /*requires that the map has no loops. does not free the root node*/
+ /*TODO*/
+ void Map_Delete_Map(struct Map *tree)
+ {
+
+ }
+ #endif //#ifndef GMAP
F diff --git a/src/misc/map.h b/src/misc/map.h new file mode 100644 --- /dev/null +++ b/src/misc/map.h
+ #ifndef GMAP_H
+ #define GMAP_H GMAP_H
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <stack.h>
+ #include <queue.h>
+ #include <assert.h>
+
+ typedef struct Map Map;
+
+
+
+ /*
+ * A looples automata with things attached to the nodes
+ * */
+ struct Map
+ {
+ char is_final;
+ Map *delta[256];
+ /*ID cannot point to itself ( this is used in the deletion of the map ) */
+ void *ID;
+ };
+
+ void Map_Init(Map *tree);
+ void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node);
+ void Map_Push(Map *tree,void *str,size_t size,void *id);
+ void* Map_Check(Map *tree, void *str,size_t size);
+ struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size);
+ void Map_Remove(Map *tree, void *str,size_t size);
+ void Map_Map(Map *tree,void (*map)(void*));
+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);
+
+ void Map_Destroy(Map *tree);
+ void Map_Delete_Map(struct Map *tree);
+ struct Condensed_Map* Map_Condense(Map* tree);
+
+ struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id);
+ /*returns NULL if id is not taken , returns pointer to taken id otherwise*/
+ void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id);
+
+ #endif
F diff --git a/src/misc/queue.c b/src/misc/queue.c new file mode 100644 --- /dev/null +++ b/src/misc/queue.c
+ #ifndef GQUEUE_C
+ #define GQUEUE_C GQUEUE_C
+ #include<queue.h>
+
+
+ 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
F diff --git a/src/misc/queue.h b/src/misc/queue.h new file mode 100644 --- /dev/null +++ b/src/misc/queue.h
+ #ifndef GQUEUE_H
+ #define GQUEUE_H GQUEUE_H
+ #include<stdlib.h>
+
+
+ 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
F diff --git a/src/misc/stack.c b/src/misc/stack.c new file mode 100644 --- /dev/null +++ b/src/misc/stack.c
+ #ifndef GSTACK_C
+ #define GSTACK_C GSTACK_C
+ #include "stack.h"
+
+
+
+ void Stack_Init(Stack *stack)
+ {
+ stack->size=0;
+ stack->first=NULL;
+ }
+ void Stack_Push(Stack *stack,void* data)
+ {
+ struct Stack_Node *temp_node=malloc(sizeof(struct Stack_Node));
+ temp_node->data=data;
+ temp_node->next=stack->first;
+ stack->first=temp_node;
+ ++stack->size;
+ }
+ void* Stack_Pop(Stack *stack)
+ {
+ void* return_value=NULL;
+ if(stack->first!=NULL)
+ {
+ struct Stack_Node *temp_first=stack->first;
+ return_value=stack->first->data;
+
+ --stack->size;
+ stack->first=stack->first->next;
+ free(temp_first);
+ }
+
+ return return_value;
+ }
+
+ #endif//#ifndef GSTACK_C
+
F diff --git a/src/misc/stack.h b/src/misc/stack.h new file mode 100644 --- /dev/null +++ b/src/misc/stack.h
+ #ifndef GSTACK_H
+ #define GSTACK_H GSTACK_H
+ #include<stdlib.h>
+ typedef struct Stack Stack;
+
+ struct Stack_Node
+ {
+ struct Stack_Node *next;
+ void *data;
+ };
+ struct Stack
+ {
+ struct Stack_Node *first;
+ size_t size;
+ };
+
+ void Stack_Init(Stack *stack);
+ void Stack_Push(Stack *stack,void* data);
+ void* Stack_Pop(Stack *stack);
+
+
+ #endif
F diff --git a/src/program/program.c b/src/program/program.c new file mode 100644 --- /dev/null +++ b/src/program/program.c
+ #ifndef PROGRAM_C
+ #define PROGRAM_C
+ #include<program.h>
+
+ 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;i<argc;++i)
+ {
+ if(!strncmp(argv[i],"--print-tokens",sizeof("--print-tokens")))
+ ret->target=OPTION_TARGET_TOKENS;
+ else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))
+ ret->target=OPTION_TARGET_AST;
+ else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output")))
+ {
+ if(++i<argc)
+ {
+ if(strnlen(argv[i],101)<100)
+ ret->src_name=argv[i];
+ else if(!ret->is_quiet)
+ {
+ fprintf(stderr,"Error: Output filename is too long");
+ exit(1);
+ }else
+ {
+ exit(1);
+ }
+ }
+ }else if(strnlen(argv[i],101)<100)
+ {
+ ret->src_name=argv[i];
+ }else if(!ret->is_quiet)
+ {
+ fprintf(stderr,"Error: Input filename is too long");
+ exit(1);
+ }else
+ {
+ exit(1);
+ }
+
+ }
+
+ if(ret->target==OPTION_DEFAULT)
+ ret->target=OPTION_TARGET_AST;
+
+ return ret;
+ }
+ struct Translation_Data* get_translation_data()
+ {
+ struct 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
F diff --git a/src/program/program.h b/src/program/program.h new file mode 100644 --- /dev/null +++ b/src/program/program.h
+ #ifndef PROGRAM_H
+ #define PROGRAM_H
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <queue.h>
+ #include <lexer.h>
+ #include <assert.h>
+
+ struct token;
+ enum Keyword;
+
+ enum Options_Target_Type
+ {
+ OPTION_TARGET_TOKENS,
+ OPTION_TARGET_AST,
+ OPTION_DEFAULT,
+ };
+
+ struct Source
+ {
+ 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
F diff --git a/stack.c b/stack.c deleted file mode 100644 --- a/stack.c +++ /dev/null
- #ifndef GSTACK_C
- #define GSTACK_C GSTACK_C
- #include "stack.h"
-
-
-
- void Stack_Init(Stack *stack)
- {
- stack->size=0;
- stack->first=NULL;
- }
- void Stack_Push(Stack *stack,void* data)
- {
- struct Stack_Node *temp_node=malloc(sizeof(struct Stack_Node));
- temp_node->data=data;
- temp_node->next=stack->first;
- stack->first=temp_node;
- ++stack->size;
- }
- void* Stack_Pop(Stack *stack)
- {
- void* return_value=NULL;
- if(stack->first!=NULL)
- {
- struct Stack_Node *temp_first=stack->first;
- return_value=stack->first->data;
-
- --stack->size;
- stack->first=stack->first->next;
- free(temp_first);
- }
-
- return return_value;
- }
-
- #endif//#ifndef GSTACK_C
-
F diff --git a/stack.h b/stack.h deleted file mode 100644 --- a/stack.h +++ /dev/null
- #ifndef GSTACK_H
- #define GSTACK_H GSTACK_H
- #include<stdlib.h>
- typedef struct Stack Stack;
-
- struct Stack_Node
- {
- struct Stack_Node *next;
- void *data;
- };
- struct Stack
- {
- struct Stack_Node *first;
- size_t size;
- };
-
- void Stack_Init(Stack *stack);
- void Stack_Push(Stack *stack,void* data);
- void* Stack_Pop(Stack *stack);
-
-
- #endif
F diff --git a/test b/test deleted file mode 100644 --- a/test +++ /dev/null
- machine flicker
- [
- states [ light_off , light_on ];
-
- starting on light_on;
-
- events [ one_second ];
- transitions
- [
- from light_on to light_off on event one_second
- execute turn_off_light;
- from light_off to light_on on event one_second
- execute turn_on_light;
- ];
- ];
-
F diff --git a/test2 b/test2 deleted file mode 100644 --- a/test2 +++ /dev/null
- "1"
- "12"
F diff --git a/test3 b/test3 deleted file mode 100644 --- a/test3 +++ /dev/null
- 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()
- {
-
- }
F diff --git a/tests/test b/tests/test new file mode 100644 --- /dev/null +++ b/tests/test
+ machine flicker
+ [
+ states [ light_off , light_on ];
+
+ starting on light_on;
+
+ events [ one_second ];
+ transitions
+ [
+ from light_on to light_off on event one_second
+ execute turn_off_light;
+ from light_off to light_on on event one_second
+ execute turn_on_light;
+ ];
+ ];
+
F diff --git a/tests/test2 b/tests/test2 new file mode 100644 --- /dev/null +++ b/tests/test2
+ "1"
+ "12"
F diff --git a/tests/test3 b/tests/test3 new file mode 100644 --- /dev/null +++ b/tests/test3
+ machine light_bulb
+ [
+ states [ light_on , light_off ];
+ events [ switch_state , turn_on , turn_off ];
+
+ starting on light_off;
+
+ transitions
+ [
+ from light_on to light_off on event switch_state execute light_switch();
+ from light_off to light_on on event switch_state execute light_switch();
+
+ from light_on to light_off on event turn_on execute light_switch();
+ from light_off to light_on on event turn_off execute light_switch();
+ ];
+ ];
+
+ transition light_switch()
+ {
+
+ }