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