aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGalin Simeonov <gts@volconst.com>2021-05-17 17:29:08 +0300
committerGalin Simeonov <gts@volconst.com>2021-07-15 18:00:15 +0300
commitf768d9bdb84e846d89aac66a4f3433a44241c298 (patch)
treeb7e8248bebd80c8b1f911f666260ad52b7213b84
parent679cbe58c4e53f0163588a7731154f3afe2d25aa (diff)
downloadMEGATRON-f768d9bdb84e846d89aac66a4f3433a44241c298.tar.gz
parser formed
-rw-r--r--.gdb_history242
-rw-r--r--lexer.c27
-rw-r--r--lexer.h9
-rw-r--r--main.c38
-rw-r--r--makefile13
-rw-r--r--map.c285
-rw-r--r--map.h41
-rw-r--r--parser.c669
-rw-r--r--parser.h124
-rw-r--r--print.c223
-rw-r--r--print.h22
-rw-r--r--program.c85
-rw-r--r--program.h27
-rw-r--r--stack.c37
-rw-r--r--stack.h22
-rw-r--r--test26
-rw-r--r--test321
17 files changed, 1862 insertions, 49 deletions
diff --git a/.gdb_history b/.gdb_history
index 6b826e1..a7d0bd7 100644
--- a/.gdb_history
+++ b/.gdb_history
@@ -131,3 +131,245 @@ s
n
n
q
+b main
+r test
+n
+record
+n
+rs
+r
+record stop
+n
+print translation_unit
+print *translation_data
+print *translation_data->errors
+n
+s
+n
+s
+r test
+print ast
+b parse_unit
+r
+r test
+s
+n
+rs
+r
+record
+r
+s
+n
+rs
+r
+s
+n
+n
+rs
+r
+n
+r
+y
+s
+n
+n
+s
+n
+n
+n
+r
+n
+r
+s
+n
+s
+n
+n
+n
+n
+n
+s
+n
+s
+n
+where
+r
+s
+n
+r
+s
+n
+s
+n
+n
+s
+print ast
+print *ast
+r
+s
+n
+s
+n
+b main
+r test
+n
+s
+s
+n
+s
+n
+n
+s
+n
+print ((struct token*)translation_data->tokens->first->data-)
+print ((struct token*)translation_data->tokens->first->data-))
+print ((struct token*)translation_data->tokens->first->data)
+print *((struct token*)translation_data->tokens->first->data)
+print ((struct token*)translation_data->tokens->first->data)->ytpe
+print ((struct token*)translation_data->tokens->first->data)->type]
+print ((struct token*)translation_data->tokens->first->data)->type
+b parse_unit
+r test
+s
+n
+r
+s
+n
+r
+s
+n
+n
+n
+n
+s
+n
+print machine_id
+print *machine_id
+n
+print (struct token*)translation_data->tokens->first->data
+print ((struct token*)translation_data->tokens->first->data)->type
+b parse_machine_inner
+r test
+n
+print states
+r
+n
+s
+n
+s
+n
+b parse_start_on
+r test
+n
+n
+print *hol
+print *hold_id
+n
+print hold_state
+print states->states_map
+print *states->states_map
+print hold_id->data
+print hold_id->data[hold_id->size]
+r
+r
+r test
+rs
+where
+print str
+b get_ast_states
+r
+n
+n
+print *state
+print *hold_state
+print *hold_state->id
+print hold_state->id->size
+s
+s
+n
+print id
+print tree
+print tree->ID
+n
+n
+s
+n
+print tree->ID
+b get_ast_states
+r
+r test
+n
+s
+print id
+print size
+print (char*)str
+print *(char*)str
+r
+n
+s
+print id
+print *(char*)str
+r
+n
+q
+r test
+print *ast
+print ast
+where
+b delete_ast_pipeline
+r
+n
+n
+print ast->pipeline
+print ast->pipeline[i]
+print *ast
+print ast->pipeline[0]
+print ast->pipeline[1]
+print ast->pipeline[2]
+print ast->pipeline[3]
+print ast->pipeline[4]
+print ast->pipeline[5]
+b get_ast_pipeline
+r
+n
+b parse_pipeline
+r
+where
+b parse_unit
+r test
+s
+n
+r
+s
+n
+r
+s
+n
+s
+n
+print starting_state
+print *starting_state
+print *starting_state->id
+n
+n
+print ( (struct token *)translation_data->tokens->first->data)->id
+print ( (struct token *)translation_data->tokens->first->data)->type
+print *translation_data
+print *translation_data->errors
+b 124
+r
+co
+c
+s
+n
+n
+n
+n
+print ( (struct token *)translation_data->tokens->first->data)->type
+rs
+r
+c
+s
+n
+s
+q
diff --git a/lexer.c b/lexer.c
index 546c727..6dc348d 100644
--- a/lexer.c
+++ b/lexer.c
@@ -29,8 +29,6 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
{
if(check_and_move_if_on_word("machine",sizeof("machine")-1,src,1))
return get_token(src->src+src->where_in_src-sizeof("machine")+1,sizeof("machine")-1,KW_MACHINE,src->current_row,src->current_column);
- if(check_and_move_if_on_word("state",sizeof("state")-1,src,1))
- return get_token(src->src+src->where_in_src-sizeof("state")+1,sizeof("state")-1,KW_STATE,src->current_row,src->current_column);
if(check_and_move_if_on_word("from",sizeof("from")-1,src,1))
return get_token(src->src+src->where_in_src-sizeof("from")+1,sizeof("from")-1,KW_FROM,src->current_row,src->current_column);
if(check_and_move_if_on_word("to",sizeof("to")-1,src,1))
@@ -39,6 +37,8 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
return get_token(src->src+src->where_in_src-sizeof("on")+1,sizeof("on")-1,KW_ON,src->current_row,src->current_column);
if(check_and_move_if_on_word("[",sizeof("[")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("[")+1,sizeof("[")-1,KW_OPEN_SQUARE,src->current_row,src->current_column);
+ if(check_and_move_if_on_word(",",sizeof(",")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof(",")+1,sizeof(",")-1,KW_COMMA,src->current_row,src->current_column);
if(check_and_move_if_on_word("]",sizeof("]")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("]")+1,sizeof("]")-1,KW_CLOSE_SQUARE,src->current_row,src->current_column);
if(check_and_move_if_on_word(";",sizeof(";")-1,src,0))
@@ -47,6 +47,16 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column);
if(check_and_move_if_on_word("starting",sizeof("starting")-1,src,1))
return get_token(src->src+src->where_in_src-sizeof("starting")+1,sizeof("starting")-1,KW_STARTING,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("states",sizeof("states")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("states")+1,sizeof("states")-1,KW_STATES,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("events",sizeof("events")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("events")+1,sizeof("events")-1,KW_EVENTS,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("execute",sizeof("execute")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("execute")+1,sizeof("execute")-1,KW_EXECUTE,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("event",sizeof("event")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("event")+1,sizeof("event")-1,KW_EVENT,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("transitions",sizeof("transitions")-1,src,1))
+ return get_token(src->src+src->where_in_src-sizeof("transitions")+1,sizeof("transitions")-1,KW_TRANSITIONS,src->current_row,src->current_column);
@@ -122,6 +132,7 @@ static char check_and_move_if_on_word(char *word,size_t word_size,struct Source
else if( (needs_space_after && isspace(src->src[src->where_in_src+i])) || !needs_space_after )
{
src->where_in_src+=i;
+ src->current_column+=i;
return 1;
}
else
@@ -132,6 +143,18 @@ static char check_and_move_if_on_word(char *word,size_t word_size,struct Source
void skip_white_space(struct Source *src)
{
while(src->where_in_src<src->src_size && isspace(src->src[src->where_in_src]))
+ {
+ if(src->src[src->where_in_src]=='\n')
+ {
+ ++src->current_row;
+ src->current_column=0;
+ }
++src->where_in_src;
+ }
+}
+
+void push_token_into_map(struct token *token,struct Map *map,void *thing)
+{
+ Map_Push(map,token->data,token->size,thing);
}
#endif
diff --git a/lexer.h b/lexer.h
index e69e23b..320146c 100644
--- a/lexer.h
+++ b/lexer.h
@@ -3,6 +3,7 @@
#include <ctype.h> //isspace
#include <program.h>
#include <queue.h>
+#include <map.h>
struct Translation_Data;
struct Source;
@@ -10,7 +11,6 @@ struct Source;
enum Keyword
{
KW_MACHINE,
- KW_STATE,
KW_FROM,
KW_TO,
KW_ON,
@@ -23,6 +23,12 @@ enum Keyword
KW_PIPE,
KW_SEMI_COLUMN,
KW_STARTING,
+ KW_STATES,
+ KW_EVENTS,
+ KW_EVENT,
+ KW_EXECUTE,
+ KW_TRANSITIONS,
+ KW_COMMA,
};
struct token
{
@@ -38,6 +44,7 @@ struct token* lex_step(struct Source *src,struct Translation_Data *translation_d
struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size_t column);
void skip_white_space(struct Source *src);
+void push_token_into_map(struct token *token,struct Map *map,void *thing);
void delete_token(struct token *token);
diff --git a/main.c b/main.c
index bfc09c0..438f282 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,9 @@
-#include<stdio.h>
-#include<program.h>
-#include<lexer.h>
-#include<string.h>
-#include<print.h>
+#include <stdio.h>
+#include <program.h>
+#include <lexer.h>
+#include <string.h>
+#include <parser.h>
+#include <print.h>
@@ -12,18 +13,18 @@ int main(int argc,char **argv)
struct Source *source;
struct Program *program;
struct Translation_Data *translation_data;
+ struct AST* translation_unit;
- options=parse_command_line(argv);
- if(options->source==NULL)
+ options=parse_command_line(argc,argv);
+ if(options->src_name==NULL)
{
printf("No source file specified\n");
return 0;
}
- source=extract_source(strdup(options->source));
+ source=extract_source(strndup(options->src_name,100));
translation_data=get_translation_data();
-
- if(options->print_tokens)
+ if(options->target==OPTION_TARGET_TOKENS || options->target==OPTION_TARGET_AST)
{
lex(translation_data->tokens,source,translation_data);
if(translation_data->errors->size>0)
@@ -31,11 +32,26 @@ int main(int argc,char **argv)
printf("There was an error!\n");
print_tokens(translation_data->tokens);
return 1;
- }else
+ }else if(options->target==OPTION_TARGET_TOKENS)
{
print_tokens(translation_data->tokens);
+ }else if(options->target==OPTION_TARGET_AST) //we check because we will probably add more options
+ {
+ translation_unit=parse_unit(translation_data);
+ if(has_new_errors(translation_data))
+ {
+ print_errors(translation_data);
+ return 1;
+ }else
+ {
+ print_ast(translation_unit);
+ delete_ast(translation_unit);
+ }
}
+ }else
+ {
+ assert(!"false");
}
delete_source(source);
diff --git a/makefile b/makefile
index 457b589..354eed1 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,7 @@
INCLUDE_DIRS=-I .
CFLAGS="-g"
-main.exe : main.c lexer.o queue.o print.o program.o
- gcc ${CFLAGS} main.c lexer.o queue.o print.o program.o -o main.exe ${INCLUDE_DIRS}
+main.exe : main.c lexer.o queue.o print.o program.o parser.o map.o stack.o
+ gcc ${CFLAGS} main.c lexer.o queue.o print.o program.o parser.o map.o stack.o -o main.exe ${INCLUDE_DIRS}
lexer.o : lexer.c lexer.h
gcc ${CFLAGS} -c lexer.c -o lexer.o ${INCLUDE_DIRS}
queue.o : queue.c queue.h
@@ -10,6 +10,11 @@ print.o : print.c print.h
gcc ${CFLAGS} -c print.c -o print.o ${INCLUDE_DIRS}
program.o : program.c program.h
gcc ${CFLAGS} -c program.c -o program.o ${INCLUDE_DIRS}
-
+parser.o : parser.c parser.h
+ gcc ${CFLAGS} -c parser.c -o parser.o ${INCLUDE_DIRS}
+map.o : map.c map.h
+ gcc ${CFLAGS} -c map.c -o map.o ${INCLUDE_DIRS}
+stack.o : stack.c stack.h
+ gcc ${CFLAGS} -c stack.c -o stack.o ${INCLUDE_DIRS}
clear:
- rm -rf lexer.o main.exe queue.o print.o program.o
+ rm -rf lexer.o main.exe queue.o print.o program.o parser.o map.o stack.o
diff --git a/map.c b/map.c
new file mode 100644
index 0000000..cd8272f
--- /dev/null
+++ b/map.c
@@ -0,0 +1,285 @@
+#ifndef GMAP_C
+#define GMAP_C GMAP_C
+#include <map.h>
+
+
+
+/*
+ * ID and residue and all of delta is assigned to NULL
+ * */
+void Map_Init(Map *tree)
+{
+ tree->is_final=0;
+ for(int i=0;i<256;++i)tree->delta[i] = NULL;
+ tree->ID = NULL;
+}
+
+void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node)
+{
+ for(
+ *where=0,*final_node=tree;
+ *where<size && final_node[0]->delta[((unsigned char*)str)[ where[0] ]]!=NULL;
+ ++where[0]
+ )
+ {
+ (*final_node) = (*final_node)->delta[((unsigned char*)str)[*where]];
+ }
+}
+
+
+
+/*
+ * tree must not be null
+ * */
+void Map_Push(Map *tree,void *str,size_t size,void *id)
+{
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ assert(tree->ID==NULL);
+ tree->ID=id;
+ tree->is_final=1;
+ return;
+ }
+ for(temp;temp<size;++temp)
+ {
+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
+ /*
+ Map_Init(
+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
+ );
+ */
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+
+}
+
+
+/*
+ * scours the tree and returns the id of the node that recognises the str
+ * returns NULL if the string is not recognised
+ * */
+void* Map_Check(Map *tree, void *str,size_t size)
+{
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp<size)
+ {
+ return NULL;
+ }else
+ {
+ return tree->ID; //this has been set to be the last reached node
+ }
+}
+
+void Map_Remove(Map *tree, void *str,size_t size)
+{
+ Stack stk;
+ Stack_Init(&stk);
+ size_t where;
+ char what_to_null=((char*)str)[0];
+
+ Stack_Push(&stk,tree);
+
+ for(where=0;where<size-1 && tree->delta[((unsigned char*)str)[where]]!=NULL;++where)
+ {
+ tree = tree->delta[((unsigned char*)str)[where]];
+ if(tree->is_final==1)
+ {
+ while(stk.size>0)Stack_Pop(&stk);
+ what_to_null=((char*)str)[where+1];
+ }
+ Stack_Push(&stk,tree);
+ }
+ if(tree->delta[((unsigned char*)str)[where]] == NULL)return;
+ free(tree->delta[((unsigned char*)str)[where]]);
+ while(stk.size>1)free(Stack_Pop(&stk));
+ tree=(Map*)Stack_Pop(&stk);
+ tree->delta[(unsigned char)what_to_null]=NULL;
+
+}
+/*This function especially requires that the map has no loops*/
+void Map_Map(Map *tree,void (*map)(void*))
+{
+ if(tree->is_final==1)map(tree->ID);
+ for(int i=0;i<256;++i)
+ {
+ if(tree->delta[i]!=NULL)
+ {
+ Map_Map(tree->delta[i],map);
+ }
+ }
+}
+
+/*first argument of map is the node id , the second is pass_data*/
+void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data)
+{
+ if(tree->is_final==1)map(tree->ID,pass_data);
+ for(int i=0;i<256;++i)
+ {
+ if(tree->delta[i]!=NULL)
+ {
+ Map_Map_Extended(tree->delta[i],map,pass_data);
+ }
+ }
+}
+
+
+/*this does not destroy(free) any memory pointed to by a node in the Map. This does not free() the root (Map *tree) */
+/*This function especially does not require that the map has no loop ( for example after grepification )*/
+void Map_Destroy(Map *tree)
+{
+ Stack path;
+ Stack nodes;
+ Map *current_node;
+ unsigned int i;
+
+
+ Stack_Init(&path);
+ Stack_Init(&nodes);
+
+ Stack_Push(&path,tree);
+ Stack_Push(&nodes,tree);
+
+ /*
+ using DFS we fill up the nodes stack with all the used
+ (accessible) nodes.
+ */
+ while(path.size>0)
+ {
+ current_node=Stack_Pop(&path);
+ current_node->ID=&(current_node->ID);/*mark the node*/
+ for(i=0;i<256;++i)
+ {
+ if(current_node->delta[i]!=NULL && current_node->delta[i]->ID != &(current_node->delta[i]->ID) )
+ {
+ Stack_Push(&path,current_node->delta[i]);
+
+
+ /*we mark the unmarked child of the current_node*/
+ current_node->delta[i]->ID=&(current_node->delta[i]->ID);
+ /*every node in nodes continues to be marked*/
+ Stack_Push(&nodes,current_node->delta[i]);
+ }
+ }
+
+ }
+ /*
+ There should not be any duplicates in here
+ */
+ while(nodes.size>1)
+ {
+ current_node=Stack_Pop(&nodes);
+ /*Again the things that ID points to is not freed ( this structure is used to map the structure of data )
+ deletion of it is up to you.
+ */
+ free(current_node);
+ }
+ /*this is where the root is at- we don't delete it , but we must free the last stack node*/
+ Stack_Pop(&nodes);
+
+
+}
+
+/*requres that cpy has no loops*/
+Map* Map_Copy(Map *cpy)
+{
+ short i;
+ Map *ret;
+
+ if(cpy==NULL)
+ {
+ return NULL;
+ }
+
+ ret=malloc(sizeof(Map));
+ ret->is_final=cpy->is_final;
+ ret->ID=cpy->ID;
+
+ for(i=0;i<256;++i)
+ {
+ ret->delta[i]=Map_Copy(cpy->delta[i]);
+ }
+ return ret;
+}
+
+struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size)
+{
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp<size)
+ {
+ return NULL;
+ }else
+ {
+ return tree;
+ }
+}
+
+struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id)
+{
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ if(tree->ID!=NULL)tree->ID=id;
+ tree->is_final=1;
+ return tree;
+ }
+
+ for(temp;temp<size;++temp)
+ {
+ Map_Init(
+ tree=
+ tree->delta[((unsigned char*)str)[temp]]=
+ malloc(sizeof(Map))
+ );
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+ return tree;
+}
+
+void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id)
+{
+ size_t temp;
+ Map_Scour(tree,str,size,&temp,&tree);
+
+ if(temp == size)
+ {
+ if(!tree->is_final)
+ {
+ tree->ID=id;
+ tree->is_final=1;
+ }
+ return tree->ID;
+ }
+ for(temp;temp<size;++temp)
+ {
+ tree=tree->delta[((unsigned char*)str)[temp]]=calloc(1,sizeof(Map));
+ /*
+ Map_Init(
+ tree=tree->delta[((unsigned char*)str)[temp]]=malloc(sizeof(Map))
+ );
+ */
+ }
+
+ tree->ID=id;
+ tree->is_final=1;
+ return NULL;
+}
+/*requires that the map has no loops. does not free the root node*/
+/*TODO*/
+void Map_Delete_Map(struct Map *tree)
+{
+
+}
+#endif //#ifndef GMAP
diff --git a/map.h b/map.h
new file mode 100644
index 0000000..ced43a7
--- /dev/null
+++ b/map.h
@@ -0,0 +1,41 @@
+#ifndef GMAP_H
+#define GMAP_H GMAP_H
+#include <stdlib.h>
+#include <stdio.h>
+#include <stack.h>
+#include <queue.h>
+#include <assert.h>
+
+typedef struct Map Map;
+
+
+
+/*
+ * A looples automata with things attached to the nodes
+ * */
+struct Map
+{
+ char is_final;
+ Map *delta[256];
+ /*ID cannot point to itself ( this is used in the deletion of the map ) */
+ void *ID;
+};
+
+void Map_Init(Map *tree);
+void Map_Scour(Map *tree,void *str,size_t size,size_t *where,Map **final_node);
+void Map_Push(Map *tree,void *str,size_t size,void *id);
+void* Map_Check(Map *tree, void *str,size_t size);
+struct Map* Map_Check_And_Get(Map *tree, void *str,size_t size);
+void Map_Remove(Map *tree, void *str,size_t size);
+void Map_Map(Map *tree,void (*map)(void*));
+void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);
+
+void Map_Destroy(Map *tree);
+void Map_Delete_Map(struct Map *tree);
+struct Condensed_Map* Map_Condense(Map* tree);
+
+struct Map* Map_Push_And_Get(struct Map* tree,void *str,size_t size,void *id);
+/*returns NULL if id is not taken , returns pointer to taken id otherwise*/
+void* Map_Check_And_Push(struct Map *tree,void *str,size_t size,void *id);
+
+#endif
diff --git a/parser.c b/parser.c
new file mode 100644
index 0000000..3e4e449
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,669 @@
+#ifndef PARSER_C
+#define PARSER_C PARSER_C
+#include <parser.h>
+
+/*
+ * parse-unit: machine
+ *
+ */
+struct AST* parse_unit(struct Translation_Data *translation_data)
+{
+ return (struct AST*)parse_machine(translation_data);
+}
+/*
+ * machine: 'machine' id '[' machine-inner ']' ';'
+ *
+ */
+struct AST_Machine* parse_machine(struct Translation_Data *translation_data)
+{
+ struct AST_Machine *ret;
+ struct token *hold_id;
+ if(get_and_check(translation_data,KW_MACHINE))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id=Queue_Pop(translation_data->tokens);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ ret=(struct AST_Machine*)parse_machine_inner(hold_id,translation_data);
+ if(has_new_errors(translation_data))
+ {
+ delete_ast_machine(ret);
+ touch_errors(translation_data);
+
+ return NULL;
+ }
+ if(get_and_check(translation_data,KW_CLOSE_SQUARE))
+ {
+ if(get_and_check(translation_data,KW_SEMI_COLUMN))
+ return ret;
+ else
+ {
+ push_parsing_error("';' expected after machine definition",translation_data);
+ delete_ast_machine(ret);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("closing ']' expected",translation_data);
+ delete_ast_machine(ret);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("opening '[' expected",translation_data);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("expected a name for the machine",translation_data);
+ return NULL;
+ }
+ }else
+ {
+ push_parsing_error("'machine' expected",translation_data);
+ return NULL;
+ }
+}
+/*
+ * machine-inner : 'states' '[' states-inner ']' ';'
+ * 'events' '[' events-inner ']' ';'
+ * 'transitions' '[' transitions-inner ']' ';'
+ * 'starting' start-on-inner ';'
+ */
+struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data)
+{
+ struct AST_States *states=NULL;
+ struct AST_Events *events=NULL;
+ struct AST_Transitions *transitions=NULL;
+ struct AST_State *starting_state=NULL;
+ unsigned char i;
+ for(i=0;i<4;++i)
+ switch(get_kw(translation_data))
+ {
+ case KW_STATES:
+ if(states)
+ {
+ push_parsing_error("defining two sets of states",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ states=parse_states_inner(translation_data);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of states definition",translation_data);
+ goto error_cleanup;
+ }
+
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_TRANSITIONS:
+ if(states==NULL && events==NULL)
+ {
+ push_parsing_error("defining transitions before states and events",translation_data);
+ goto error_cleanup;
+ }else if(transitions)
+ {
+ push_parsing_error("defining two sets of transitions",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ transitions=parse_transitions_inner(translation_data,states,events);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of transitions definition",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_EVENTS:
+ if(events)
+ {
+ push_parsing_error("defining two sets of transitions",translation_data);
+ goto error_cleanup;
+ }else
+ {
+ chomp(translation_data);
+ if(get_and_check(translation_data,KW_OPEN_SQUARE))
+ {
+ events=parse_events_inner(translation_data);
+ if(!get_and_check(translation_data,KW_CLOSE_SQUARE)
+ || !get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ']' and ';' at "
+ "end of events definition",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("expected '[' ",translation_data);
+ goto error_cleanup;
+ }
+ }
+ break;
+ case KW_STARTING:
+ chomp(translation_data);
+ if(!starting_state)
+ {
+ if(states)
+ {
+ starting_state=parse_start_on(translation_data,states);
+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ push_parsing_error("expected ';' at end "
+ "of starting state declaration",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("states need to be defined"
+ " before defining a starting one",translation_data);
+ goto error_cleanup;
+ }
+ }else
+ {
+ push_parsing_error("starting state is defined",translation_data);
+ goto error_cleanup;
+ }
+ break;
+ default:
+ push_parsing_error("expected states transitions or events",translation_data);
+ goto error_cleanup;
+
+ }
+
+ return get_ast_machine(machine_id,states,events,transitions,starting_state);
+
+error_cleanup:
+ push_parsing_error("in machine",translation_data);
+ if(states)delete_ast_states(states);
+ if(events)delete_ast_events(events);
+ if(transitions)delete_ast_transitions(transitions);
+ return NULL;
+}
+/*
+ * states-inner: state (, state)*
+ *
+ */
+struct AST_States* parse_states_inner(struct Translation_Data *translation_data)
+{
+ struct Queue *ids;
+ struct AST_State *hold_state;
+
+ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_state,translation_data,KW_COMMA);
+ if(ids->size==0)
+ {
+ push_parsing_error("there needs to be atleast one state",translation_data);
+ free(ids);
+ return NULL;
+ }else
+ {
+
+ return get_ast_states(ids);
+ }
+}
+/*
+ * state : id
+ *
+ */
+struct AST_State* parse_state(struct Translation_Data *translation_data)
+{
+ if(get_kw(translation_data)==KW_ID)
+ return get_ast_state(Queue_Pop(translation_data->tokens));
+ else
+ return NULL;
+}
+/*
+ * events-inner: id (, id)*
+ *
+ */
+struct AST_Events* parse_events_inner(struct Translation_Data *translation_data)
+{
+ struct Queue *ids;
+ ids=parse_list((struct AST*(*)(struct Translation_Data*))parse_event,translation_data,KW_COMMA);
+ if(ids->size==0)
+ {
+ push_parsing_error("there needs to be atleast one event",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_events(ids);
+ }
+}
+struct AST_Event* parse_event(struct Translation_Data *translation_data)
+{
+ if(get_kw(translation_data)==KW_ID)
+ return get_ast_event(Queue_Pop(translation_data->tokens));
+ else
+ return NULL;
+}
+/*
+ * transitions-inner: ( transition ;)*
+ */
+struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+{
+ struct Queue *transitions;
+ struct AST_Transition *hold_transition;
+
+ transitions=malloc(sizeof(struct Queue));
+ Queue_Init(transitions);
+
+ while((hold_transition=parse_transition(translation_data,states,events))!=NULL)
+ {
+ Queue_Push(transitions,hold_transition);
+ if(!get_and_check(translation_data,KW_SEMI_COLUMN))
+ break;
+ }
+
+ if(transitions->size==0)
+ {
+ push_parsing_error("there are no transitions",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_transitions(transitions);
+ }
+}
+/*
+ * transition: 'from' state_id 'to' state_id 'on' 'event' event_id [ 'execute' pipeline ]
+ *
+ */
+struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+{
+ struct AST_Transition *ret;
+ struct AST_State *hold_from;
+ struct AST_State *hold_to;
+ struct AST_Event *hold_event;
+ struct AST_Pipeline *hold_pipeline=NULL;
+ struct token *hold_token;
+
+ if(get_and_check(translation_data,KW_FROM))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_from!=NULL)
+ {
+ if(get_and_check(translation_data,KW_TO))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_to=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_to!=NULL)
+ {
+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_event=Map_Check(events->events_map,hold_token->data,hold_token->size);
+ delete_token(hold_token);
+ if(hold_event!=NULL)
+ {
+ if(get_and_check(translation_data,KW_EXECUTE))
+ if((hold_pipeline=parse_pipeline(translation_data))==NULL)
+ { push_parsing_error("after execute",translation_data); return NULL; }
+ /*GOAL*/
+ return get_ast_transition(hold_from,hold_to,hold_event,hold_pipeline);
+ }else { push_parsing_error("event not defined",translation_data); return NULL; }
+ }else { push_parsing_error("no event name given in transition",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'on event'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined to state in transition",translation_data); }
+ }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'to'",translation_data); return NULL; }
+ }else { push_parsing_error("using undefined from state in transition",translation_data); return NULL; }
+ }else { push_parsing_error("expected id in transition expression",translation_data); return NULL; }
+ }else { return NULL; }
+}
+/*
+ * pipeline: [ command ( | command )* ]
+ *
+ */
+struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data)
+{
+ struct Queue *pipeline;
+ pipeline=parse_list((struct AST*(*)(struct Translation_Data*))parse_command,translation_data,KW_PIPE);
+ if(pipeline->size==0)
+ {
+ free(pipeline);
+ push_parsing_error("pipeline is empty",translation_data);
+ return NULL;
+ }else
+ {
+ return get_ast_pipeline(pipeline);
+ }
+}
+/*
+ * command: id [ string ]
+ *
+ */
+struct AST_Command* parse_command(struct Translation_Data *translation_data)
+{
+ struct token *id;
+ struct token *string=NULL;
+ if(get_kw(translation_data)==KW_ID)
+ {
+ id=Queue_Pop(translation_data->tokens);
+ if(get_kw(translation_data)==KW_STRING)
+ string=Queue_Pop(translation_data->tokens);
+ return get_ast_command(id,string);
+ }else
+ {
+ push_parsing_error("expected command id",translation_data);
+ return NULL;
+ }
+}
+/*
+ * starting-on-inner: 'on' id ;
+ */
+struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states)
+{
+ struct token *hold_id;
+ struct AST_State *hold_state;
+
+ if(get_and_check(translation_data,KW_ON))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id=Queue_Pop(translation_data->tokens);
+ hold_state=Map_Check(states->states_map,hold_id->data,hold_id->size);
+ free(hold_id);
+ if(hold_state)
+ {
+
+ return hold_state;
+
+ }else { push_parsing_error("starting state is not defined",translation_data); return NULL; }
+ }else { push_parsing_error("expected an identifier for starting state",translation_data); return NULL; }
+ }else { push_parsing_error("expected 'on'",translation_data); return NULL; }
+}
+struct AST_State* get_ast_state(struct token *id)
+{
+ struct AST_State *ret;
+
+ ret=malloc(sizeof(struct AST_State));
+ ret->type=AST_TYPE_STATE;
+ ret->id=id;
+
+ return ret;
+}
+struct AST_Event* get_ast_event(struct token *id)
+{
+ struct AST_Event *ret;
+
+ ret=malloc(sizeof(struct AST_Event));
+ ret->type=AST_TYPE_EVENT;
+ ret->id=id;
+
+ return ret;
+}
+struct AST_States* get_ast_states(struct Queue *states)
+{
+ struct AST_States *ret;
+ struct AST_State *hold_state;
+
+ /*perhaps no states error should be handled here*/
+ assert(states && states->size>0);
+
+ ret=malloc(sizeof(struct AST_States)+sizeof(struct AST_Event *[states->size]));
+ ret->type=AST_TYPE_STATES;
+ ret->number_of_states=states->size;
+ ret->states_map=malloc(sizeof(struct Map));
+
+ Map_Init(ret->states_map);
+
+ while(states->size>0)
+ {
+ hold_state=Queue_Pop(states);
+ Map_Push(ret->states_map,hold_state->id->data,hold_state->id->size,hold_state);
+ ret->states[states->size]=hold_state;
+ }
+
+ assert(states->size==0);
+ free(states);
+
+ return ret;
+}
+struct AST_Events* get_ast_events(struct Queue *events)
+{
+ struct AST_Events *ret;
+ struct AST_Event *hold_event;
+
+ /*perhaps no events error should be handled here*/
+ assert(events && events->size>0);
+
+ ret=malloc(sizeof(struct AST_Events)+sizeof(struct AST_Event *[events->size]));
+ ret->type=AST_TYPE_EVENTS;
+ ret->number_of_events=events->size;
+ ret->events_map=malloc(sizeof(struct Map));
+
+ Map_Init(ret->events_map);
+
+ while(events->size>0)
+ {
+ hold_event=Queue_Pop(events);
+ Map_Push(ret->events_map,hold_event->id->data,hold_event->id->size,hold_event);
+ ret->events[events->size]=hold_event;
+ }
+
+ assert(events->size==0);
+ free(events);
+
+ return ret;
+}
+struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline)
+{
+ struct AST_Transition *ret;
+ ret=malloc(sizeof(struct AST_Transition));
+ ret->type=AST_TYPE_TRANSITION;
+ ret->from=from;
+ ret->to=to;
+ ret->event=event;
+ ret->pipeline=pipeline;
+
+ return ret;
+}
+struct AST_Command* get_ast_command(struct token *function_name,struct token *argument)
+{
+ struct AST_Command *ret;
+ ret=malloc(sizeof(struct AST_Command));
+ ret->type=AST_TYPE_COMMAND;
+ ret->function_name=function_name;
+ ret->argument=argument;
+
+ return ret;
+}
+struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline)
+{
+ struct AST_Pipeline *ret;
+
+ ret=malloc(sizeof(struct AST_Pipeline)+sizeof(struct AST_Command *[pipeline->size]));
+ ret->type=AST_TYPE_PIPELINE;
+ ret->size=pipeline->size;
+ pointer_array_fill((void**)ret->pipeline,pipeline);
+
+ assert(pipeline->size==0);
+ free(pipeline);
+
+ return ret;
+}
+struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state)
+{
+ struct AST_Machine *ret;
+
+ ret=malloc(sizeof(struct AST_Machine));
+ ret->type=AST_TYPE_MACHINE;
+ ret->id=id;
+ ret->states=states;
+ ret->events=events;
+ ret->transitions=transitions;
+
+ return ret;
+}
+struct AST_Transitions* get_ast_transitions(struct Queue *transitions)
+{
+ struct AST_Transitions *ret;
+ ret=malloc(sizeof(struct AST_Transitions)+sizeof(struct AST_Transition *[transitions->size]));
+ ret->type=AST_TYPE_TRANSITIONS;
+ ret->size=transitions->size;
+
+ pointer_array_fill((void**)ret->transitions,transitions);
+
+ assert(transitions->size==0);
+ free(transitions);
+
+ return ret;
+}
+void delete_ast(struct AST* ast)
+{
+ switch(ast->type)
+ {
+ case AST_TYPE_MACHINE:
+ delete_ast_machine((struct AST_Machine*)ast);
+ break;
+ case AST_TYPE_STATE:
+ delete_ast_state((struct AST_State*)ast);
+ break;
+ case AST_TYPE_STATES:
+ delete_ast_states((struct AST_States*)ast);
+ break;
+ case AST_TYPE_EVENT:
+ delete_ast_event((struct AST_Event*)ast);
+ break;
+ case AST_TYPE_EVENTS:
+ delete_ast_events((struct AST_Events*)ast);
+ break;
+ case AST_TYPE_TRANSITION:
+ delete_ast_transition((struct AST_Transition*)ast);
+ break;
+ case AST_TYPE_TRANSITIONS:
+ delete_ast_transitions((struct AST_Transitions*)ast);
+ break;
+ case AST_TYPE_COMMAND:
+ delete_ast_command((struct AST_Command*)ast);
+ break;
+ case AST_TYPE_PIPELINE:
+ delete_ast_pipeline((struct AST_Pipeline*)ast);
+ break;
+ }
+}
+void delete_ast_event(struct AST_Event* ast)
+{
+ if(ast==NULL)return;
+ delete_token(ast->id);
+ free(ast);
+}
+void delete_ast_states(struct AST_States* ast)
+{
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->number_of_states;++i)
+ delete_ast_state(ast->states[i]);
+ free(ast);
+}
+void delete_ast_events(struct AST_Events* ast)
+{
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->number_of_events;++i)
+ delete_ast_event(ast->events[i]);
+ free(ast);
+}
+void delete_ast_transition(struct AST_Transition* ast)
+{
+ if(ast==NULL)return;
+ if(ast->pipeline!=NULL)
+ delete_ast_pipeline(ast->pipeline);
+ free(ast);
+}
+void delete_ast_command(struct AST_Command* ast)
+{
+ if(ast==NULL)return;
+ delete_token(ast->function_name);
+ if(ast->argument!=NULL)
+ delete_token(ast->argument);
+ free(ast);
+}
+void delete_ast_pipeline(struct AST_Pipeline* ast)
+{
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->size;++i)
+ delete_ast_command(ast->pipeline[i]);
+ free(ast);
+}
+void delete_ast_machine(struct AST_Machine* ast)
+{
+ if(ast==NULL)return;
+ if(ast->id!=NULL)
+ delete_token(ast->id);
+ if(ast->states!=NULL)
+ delete_ast_states(ast->states);
+ if(ast->events!=NULL)
+ delete_ast_events(ast->events);
+ if(ast->transitions!=NULL)
+ delete_ast_transitions(ast->transitions);
+}
+void delete_ast_transitions(struct AST_Transitions* ast)
+{
+ size_t i;
+ if(ast==NULL)return;
+ for(i=0;i<ast->size;++i)
+ delete_ast_transition(ast->transitions[i]);
+ free(ast);
+}
+void delete_ast_state(struct AST_State* ast)
+{
+ if(ast==NULL)return;
+ if(ast->id!=NULL)
+ delete_token(ast->id);
+ free(ast);
+}
+void pointer_array_fill(void **array,struct Queue *q)
+{
+ size_t i;
+ for(i=0;q->size>0;++i)
+ array[i]=Queue_Pop(q);
+}
+
+struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim)
+{
+ struct Queue *q;
+ struct AST* hold_ast;
+
+ q=malloc(sizeof(struct Queue));
+ Queue_Init(q);
+ while(hold_ast=parser(translation_data))
+ {
+ Queue_Push(q,hold_ast);
+ if(!get_and_check(translation_data,delim))
+ break;
+ }
+ return q;
+}
+
+#endif
diff --git a/parser.h b/parser.h
new file mode 100644
index 0000000..ef82184
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,124 @@
+#ifndef PARSER_H
+#define PARSER_H PARSER_H
+#include <program.h>
+#include <stddef.h>
+#include <assert.h>
+#include <map.h>
+
+enum AST_Type
+{
+ AST_TYPE_MACHINE,
+ AST_TYPE_STATE,
+ AST_TYPE_STATES,
+ AST_TYPE_EVENT,
+ AST_TYPE_EVENTS,
+ AST_TYPE_TRANSITION,
+ AST_TYPE_TRANSITIONS,
+ AST_TYPE_COMMAND,
+ AST_TYPE_PIPELINE,
+};
+struct AST
+{
+ enum AST_Type type;
+};
+struct AST_State
+{
+ enum AST_Type type;
+ struct token *id;
+};
+struct AST_Event
+{
+ enum AST_Type type;
+ struct token *id;
+};
+struct AST_States
+{
+ enum AST_Type type;
+ size_t number_of_states;
+ struct Map *states_map;
+ struct AST_State *states[];
+};
+struct AST_Events
+{
+ enum AST_Type type;
+ size_t number_of_events;
+ struct Map *events_map;
+ struct AST_Event *events[];
+};
+struct AST_Transition
+{
+ enum AST_Type type;
+ struct AST_State *from;
+ struct AST_State *to;
+ struct AST_Event *event;
+ struct AST_Pipeline *pipeline;
+};
+struct AST_Command
+{
+ enum AST_Type type;
+ struct token *function_name;
+ struct token *argument;
+};
+struct AST_Pipeline
+{
+ enum AST_Type type;
+ size_t size;
+ struct AST_Command *pipeline[];
+};
+struct AST_Machine
+{
+ enum AST_Type type;
+ struct token *id;
+ struct AST_States *states;
+ struct AST_Events *events;
+ struct AST_Transitions *transitions;
+};
+struct AST_Transitions
+{
+ enum AST_Type type;
+ size_t size;
+ struct AST_Transition *transitions[];
+};
+
+
+struct AST* parse_unit(struct Translation_Data *translation_data);
+struct AST_Machine* parse_machine(struct Translation_Data *translation_data);
+struct AST_Machine* parse_machine_inner(struct token *machine_id,struct Translation_Data *translation_data);
+struct AST_States* parse_states_inner(struct Translation_Data *translation_data);
+struct AST_State* parse_state(struct Translation_Data *translation_data);
+struct AST_Events* parse_events_inner(struct Translation_Data *translation_data);
+struct AST_Event* parse_event(struct Translation_Data *translation_data);
+struct AST_Transitions* parse_transitions_inner(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events );
+struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events);
+struct AST_Pipeline* parse_pipeline(struct Translation_Data *translation_data);
+struct AST_Command* parse_command(struct Translation_Data *translation_data);
+struct AST_State* parse_start_on(struct Translation_Data *translation_data,struct AST_States *states);
+
+
+struct AST_State* get_ast_state(struct token *id);
+struct AST_Event* get_ast_event(struct token *id);
+struct AST_States* get_ast_states(struct Queue *states);
+struct AST_Events* get_ast_events(struct Queue *events);
+struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
+struct AST_Command* get_ast_command(struct token *function_name,struct token *argument);
+struct AST_Pipeline* get_ast_pipeline(struct Queue *pipeline);
+struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,struct AST_Events *events,struct AST_Transitions *transitions,struct AST_State *starting_state);
+struct AST_Transitions* get_ast_transitions(struct Queue *transitions);
+
+
+void delete_ast(struct AST* ast);
+void delete_ast_event(struct AST_Event* ast);
+void delete_ast_states(struct AST_States* ast);
+void delete_ast_state(struct AST_State* ast);
+void delete_ast_events(struct AST_Events* ast);
+void delete_ast_transition(struct AST_Transition* ast);
+void delete_ast_command(struct AST_Command* ast);
+void delete_ast_pipeline(struct AST_Pipeline* ast);
+void delete_ast_machine(struct AST_Machine* ast);
+void delete_ast_transitions(struct AST_Transitions* ast);
+
+
+void pointer_array_fill(void **array,struct Queue *q);
+struct Queue* parse_list(struct AST *(*parser)(struct Translation_Data*),struct Translation_Data *translation_data,enum Keyword delim);
+
+#endif
diff --git a/print.c b/print.c
index a9ec939..614a6c9 100644
--- a/print.c
+++ b/print.c
@@ -9,9 +9,6 @@ void print_keyword_enum(enum Keyword code)
case KW_MACHINE:
printf("KW_MACHINE");
break;
- case KW_STATE:
- printf("KW_STATE");
- break;
case KW_FROM:
printf("KW_FROM");
break;
@@ -48,6 +45,24 @@ void print_keyword_enum(enum Keyword code)
case KW_STARTING:
printf("KW_STARTING");
break;
+ case KW_STATES:
+ printf("KW_STATES");
+ break;
+ case KW_EVENTS:
+ printf("KW_EVENTS");
+ break;
+ case KW_EVENT:
+ printf("KW_EVENT");
+ break;
+ case KW_TRANSITIONS:
+ printf("KW__TRANSITIONS");
+ break;
+ case KW_EXECUTE:
+ printf("KW_EXECUTE");
+ break;
+ case KW_COMMA:
+ printf("KW_COMMA");
+ break;
default:
printf("LEXERROR");
}
@@ -55,6 +70,7 @@ void print_keyword_enum(enum Keyword code)
void print_token(struct token *token)
{
size_t i;
+ assert(token);
printf("[ ");
print_keyword_enum(token->type);
@@ -67,11 +83,212 @@ void print_token(struct token *token)
void print_tokens(struct Queue *tokens)
{
struct Queue_Node *it;
+ assert(tokens);
+
for(it=tokens->first;it!=NULL;it=it->prev)
{
print_token( (struct token*)(it->data));
printf(" ");
}
}
+void print_ast_enum(enum AST_Type type)
+{
+ switch(type)
+ {
+ case AST_TYPE_MACHINE:
+ printf("AST_TYPE_MACHINE");
+ break;
+ case AST_TYPE_STATE:
+ printf("AST_TYPE_STATE");
+ break;
+ case AST_TYPE_STATES:
+ printf("AST_TYPE_STATES");
+ break;
+ case AST_TYPE_EVENT:
+ printf("AST_TYPE_EVENT");
+ break;
+ case AST_TYPE_EVENTS:
+ printf("AST_TYPE_EVENTS");
+ break;
+ case AST_TYPE_TRANSITION:
+ printf("AST_TYPE_TRANSITION");
+ break;
+ case AST_TYPE_TRANSITIONS:
+ printf("AST_TYPE_TRANSITIONS");
+ break;
+ case AST_TYPE_COMMAND:
+ printf("AST_TYPE_COMMAND");
+ break;
+ case AST_TYPE_PIPELINE:
+ printf("AST_TYPE_PIPELINE");
+ break;
+ default:
+ printf("AST_NOP");
+ }
+
+}
+void print_ast(struct AST *tree)
+{
+ assert(tree);
+
+ switch(tree->type)
+ {
+ case AST_TYPE_MACHINE:
+ print_ast_machine((struct AST_Machine*)tree);
+ break;
+ case AST_TYPE_STATE:
+ print_ast_state((struct AST_State*)tree);
+ break;
+ case AST_TYPE_STATES:
+ print_ast_states((struct AST_States*)tree);
+ break;
+ case AST_TYPE_EVENT:
+ print_ast_event((struct AST_Event*)tree);
+ break;
+ case AST_TYPE_EVENTS:
+ print_ast_events((struct AST_Events*)tree);
+ break;
+ case AST_TYPE_TRANSITION:
+ print_ast_transition((struct AST_Transition*)tree);
+ break;
+ case AST_TYPE_TRANSITIONS:
+ print_ast_transitions((struct AST_Transitions*)tree);
+ break;
+ case AST_TYPE_COMMAND:
+ print_ast_command((struct AST_Command*)tree);
+ break;
+ case AST_TYPE_PIPELINE:
+ print_ast_pipeline((struct AST_Pipeline*)tree);
+ break;
+ default:
+ printf("noast");
+ }
+}
+void print_ast_state(struct AST_State* tree)
+{
+ assert(tree);
+
+ printf("[ STATE: ");
+ print_ast_enum(tree->type);
+ printf("]");
+}
+void print_ast_event(struct AST_Event* tree)
+{
+ assert(tree);
+
+ printf("[ EVENT: ");
+ print_ast_enum(tree->type);
+ printf("]");
+}
+void print_ast_states(struct AST_States* tree)
+{
+ size_t i;
+ assert(tree);
+
+ printf("STATES [\n");
+ for(i=0;i<tree->number_of_states;++i)
+ {
+ print_ast_state(tree->states[i]);
+ printf(" ");
+ }
+ printf("\n ] END STATES \n");
+}
+void print_ast_events(struct AST_Events* tree)
+{
+ size_t i;
+ assert(tree);
+ printf("EVENTS [\n");
+ for(i=0;i<tree->number_of_events;++i)
+ {
+ print_ast_event(tree->events[i]);
+ printf(" ");
+ }
+ printf("\n ] END EVENTS \n");
+}
+void print_ast_transition(struct AST_Transition* tree)
+{
+ assert(tree);
+
+ printf("TRANSITION [\nFROM");
+ print_ast_state(tree->from);
+ printf(" TO ");
+ print_ast_state(tree->to);
+ printf(" COMMAND {");
+ if(tree->pipeline==NULL)
+ {
+ printf("NULL");
+ }else
+ {
+ print_ast_pipeline(tree->pipeline);
+ }
+
+}
+void print_ast_command(struct AST_Command* tree)
+{
+ assert(tree);
+
+ printf("( command ");
+ print_token(tree->function_name);
+ if(tree->argument==NULL)
+ {
+ printf(" NOARGUMENTS ");
+ }else
+ {
+ printf(" \"");
+ print_token(tree->argument);
+ printf("\" ");
+ }
+ printf(")");
+}
+void print_ast_pipeline(struct AST_Pipeline* tree)
+{
+ size_t i;
+ assert(tree);
+ printf("PIPELINE <");
+ for(i=0;i<tree->size;++i)
+ {
+ print_ast_command(tree->pipeline[i]);
+ printf(" | ");
+ }
+ printf("> PIPELINE_END");
+}
+void print_ast_machine(struct AST_Machine* tree)
+{
+ assert(tree);
+ printf("MACHINE ");
+ print_token(tree->id);
+ printf(" [\n");
+ print_ast_states(tree->states);
+ print_ast_events(tree->events);
+ print_ast_transitions(tree->transitions);
+ printf("] MACHINE_END\n");
+}
+void print_ast_transitions(struct AST_Transitions* tree)
+{
+ size_t i;
+ assert(tree);
+ printf("TRANSITIONS [\n");
+ for(i=0;i<tree->size;++i)
+ {
+ print_ast_transition(tree->transitions[i]);
+ printf("\n");
+ }
+ printf("] TRANSITIONS_END\n");
+}
+void print_error(struct Error *error)
+{
+ assert(error);
+ printf("Error: %s, line %ld row %ld\n",error->message,error->row,error->column);
+}
+void print_errors(struct Translation_Data *translation_data)
+{
+ struct Queue_Node *it;
+ assert(translation_data);
+
+ for(it=translation_data->errors->first;it!=NULL;it=it->prev)
+ {
+ print_error(it->data);
+ }
+}
#endif
diff --git a/print.h b/print.h
index c4e3bec..54d47ce 100644
--- a/print.h
+++ b/print.h
@@ -1,11 +1,27 @@
#ifndef PRINT_H
#define PRINT_H PRINT_H
-#include<stdio.h>
-#include<lexer.h>
-#include<queue.h>
+#include <stdio.h>
+#include <lexer.h>
+#include <parser.h>
+#include <queue.h>
void print_keyword_enum(enum Keyword code);
void print_token(struct token *token);
void print_tokens(struct Queue *tokens);
+
+void print_ast_enum(enum AST_Type type);
+void print_ast(struct AST *tree);
+void print_ast_state(struct AST_State* tree);
+void print_ast_event(struct AST_Event* tree);
+void print_ast_states(struct AST_States* tree);
+void print_ast_events(struct AST_Events* tree);
+void print_ast_transition(struct AST_Transition* tree);
+void print_ast_command(struct AST_Command* tree);
+void print_ast_pipeline(struct AST_Pipeline* tree);
+void print_ast_machine(struct AST_Machine* tree);
+void print_ast_transitions(struct AST_Transitions* tree);
+
+void print_error(struct Error *error);
+void print_errors(struct Translation_Data *translation_data);
#endif
diff --git a/program.c b/program.c
index c2140c1..5cf8cc3 100644
--- a/program.c
+++ b/program.c
@@ -30,14 +30,56 @@ struct Source* extract_source(char *src_name)
fclose(file);
return ret;
}
-struct Options* parse_command_line(char **argv)
+struct Options* parse_command_line(int argc,char **argv)
{
struct Options *ret;
- size_t i;
+ int i;
+
+ assert(argv!=NULL && argc>0);
ret=malloc(sizeof(struct Options));
- ret->print_tokens=1;
- ret->source=argv[1];
+ ret->target=OPTION_DEFAULT;
+ ret->src_name=NULL;
+ ret->is_quiet=0;
+
+ for(i=0;i<argc;++i)
+ {
+ if(!strncmp(argv[i],"--print-tokens",sizeof("--print-tokens")))
+ ret->target=OPTION_TARGET_TOKENS;
+ else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))
+ ret->target=OPTION_TARGET_AST;
+ else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output")))
+ {
+ if(++i<argc)
+ {
+ if(strnlen(argv[i],101)<100)
+ ret->src_name=argv[i];
+ else if(!ret->is_quiet)
+ {
+ fprintf(stderr,"Error: Output filename is too long");
+ exit(1);
+ }else
+ {
+ exit(1);
+ }
+ }
+ }else if(strnlen(argv[i],101)<100)
+ {
+ ret->src_name=argv[i];
+ }else if(!ret->is_quiet)
+ {
+ fprintf(stderr,"Error: Input filename is too long");
+ exit(1);
+ }else
+ {
+ exit(1);
+ }
+
+ }
+
+ if(ret->target==OPTION_DEFAULT)
+ ret->target=OPTION_TARGET_AST;
+
return ret;
}
struct Translation_Data* get_translation_data()
@@ -59,16 +101,18 @@ struct Error* get_error(char *message,size_t row,size_t column)
struct Error *ret;
ret=malloc(sizeof(struct Error));
ret->message=message;
- ret->row=row;
- ret->column=column;
+ ret->row=row+1;
+ ret->column=column+1;
}
void push_lexing_error(char *error_message,struct Source *src,struct Translation_Data *translation_data)
{
Queue_Push(translation_data->errors,get_error(error_message,src->current_row,src->current_column));
}
-void push_parsing_error(char *error_message,struct token *token ,struct Translation_Data *translation_data)
+void push_parsing_error(char *error_message,struct Translation_Data *translation_data)
{
- Queue_Push(translation_data->errors,get_error(error_message,token->row,token->column));
+ struct token *error_token;
+ error_token=Queue_Pop(translation_data->tokens);
+ Queue_Push(translation_data->errors,get_error(error_message,error_token->row,error_token->column));
}
char has_new_errors(struct Translation_Data *translation_data)
{
@@ -111,4 +155,29 @@ void delete_error(struct Error *error)
free(error->message);
free(error);
}
+char get_and_check(struct Translation_Data *translation_data,enum Keyword kw)
+{
+ if( ( (struct token *)translation_data->tokens->first->data)->type==kw)
+ {
+ delete_token(Queue_Pop(translation_data->tokens));
+ return 1;
+ }else
+ {
+ return 0;
+ }
+}
+enum Keyword get_kw(struct Translation_Data *translation_data)
+{
+ return ( (struct token*)translation_data->tokens->first->data)->type;
+}
+void chomp(struct Translation_Data *translation_data)
+{
+ assert(translation_data->tokens->size>0);
+ delete_token(Queue_Pop(translation_data->tokens));
+}
+void touch_errors(struct Translation_Data *translation_data)
+{
+ assert(translation_data->hold_number_of_errors>0);
+ --translation_data->hold_number_of_errors;
+}
#endif
diff --git a/program.h b/program.h
index 8445fa3..d5e45b7 100644
--- a/program.h
+++ b/program.h
@@ -1,11 +1,21 @@
#ifndef PROGRAM_H
#define PROGRAM_H
-#include <queue.h>
-#include <lexer.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
+#include <queue.h>
+#include <lexer.h>
+#include <assert.h>
struct token;
+enum Keyword;
+
+enum Options_Target_Type
+{
+ OPTION_TARGET_TOKENS,
+ OPTION_TARGET_AST,
+ OPTION_DEFAULT,
+};
struct Source
{
@@ -20,8 +30,9 @@ struct Source
struct Options
{
- int print_tokens:1;
- char *source;
+ enum Options_Target_Type target;
+ int is_quiet:1;
+ char *src_name;
};
struct Error
@@ -44,13 +55,17 @@ struct Program
};
struct Source* extract_source(char *src_name);
-struct Options* parse_command_line(char **argv);
+struct Options* parse_command_line(int argc,char **argv);
struct Translation_Data* get_translation_data();
struct Error* get_error(char *message,size_t row,size_t column);
void push_lexing_error(char *error_message,struct Source *src,struct Translation_Data *translation_data);
-void push_parsing_error(char *error_message,struct token *token ,struct Translation_Data *translation_data);
+void push_parsing_error(char *error_message,struct Translation_Data *translation_data);
char has_new_errors(struct Translation_Data *translation_data);
+void touch_errors(struct Translation_Data *translation_data);
+char get_and_check(struct Translation_Data *translation_data,enum Keyword kw);
+enum Keyword get_kw(struct Translation_Data *translation_data);
+void chomp(struct Translation_Data *translation_data);
void delete_translation_data(struct Translation_Data *data);
void delete_source(struct Source *src);
diff --git a/stack.c b/stack.c
new file mode 100644
index 0000000..272732f
--- /dev/null
+++ b/stack.c
@@ -0,0 +1,37 @@
+#ifndef GSTACK_C
+#define GSTACK_C GSTACK_C
+#include "stack.h"
+
+
+
+void Stack_Init(Stack *stack)
+{
+ stack->size=0;
+ stack->first=NULL;
+}
+void Stack_Push(Stack *stack,void* data)
+{
+ struct Stack_Node *temp_node=malloc(sizeof(struct Stack_Node));
+ temp_node->data=data;
+ temp_node->next=stack->first;
+ stack->first=temp_node;
+ ++stack->size;
+}
+void* Stack_Pop(Stack *stack)
+{
+ void* return_value=NULL;
+ if(stack->first!=NULL)
+ {
+ struct Stack_Node *temp_first=stack->first;
+ return_value=stack->first->data;
+
+ --stack->size;
+ stack->first=stack->first->next;
+ free(temp_first);
+ }
+
+ return return_value;
+}
+
+#endif//#ifndef GSTACK_C
+
diff --git a/stack.h b/stack.h
new file mode 100644
index 0000000..14e557a
--- /dev/null
+++ b/stack.h
@@ -0,0 +1,22 @@
+#ifndef GSTACK_H
+#define GSTACK_H GSTACK_H
+#include<stdlib.h>
+typedef struct Stack Stack;
+
+struct Stack_Node
+{
+ struct Stack_Node *next;
+ void *data;
+};
+struct Stack
+{
+ struct Stack_Node *first;
+ size_t size;
+};
+
+void Stack_Init(Stack *stack);
+void Stack_Push(Stack *stack,void* data);
+void* Stack_Pop(Stack *stack);
+
+
+#endif
diff --git a/test b/test
index 3549fc5..c976a6d 100644
--- a/test
+++ b/test
@@ -1,12 +1,16 @@
-machine temp_switch
-[
- state above_treshold;
- starting state below_treshold;
-
- from below_treshold to above_treshold
- on event above_temperature "10";
- from above_treshold to below_treshold
- on event below_temperature "9";
- on state above_treshold
- on event get_temp | html_encase | http_out ;
+machine flicker
+[
+ states [ light_off , light_on ];
+
+ starting on light_on;
+
+ events [ one_second ];
+ transitions
+ [
+ from light_on to light_off on event one_second
+ execute turn_off_light;
+ from light_off to light_on on event one_second
+ execute turn_on_light;
+ ];
];
+
diff --git a/test3 b/test3
new file mode 100644
index 0000000..43e47d1
--- /dev/null
+++ b/test3
@@ -0,0 +1,21 @@
+machine light_bulb
+[
+ states [ light_on , light_off ];
+ events [ switch_state , turn_on , turn_off ];
+
+ starting on light_off;
+
+ transitions
+ [
+ from light_on to light_off on event switch_state execute light_switch();
+ from light_off to light_on on event switch_state execute light_switch();
+
+ from light_on to light_off on event turn_on execute light_switch();
+ from light_off to light_on on event turn_off execute light_switch();
+ ];
+];
+
+transition light_switch()
+{
+
+}