aboutsummaryrefslogtreecommitdiffstats
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/lexer.c18
-rw-r--r--src/frontend/lexer.h7
-rw-r--r--src/frontend/parser.c281
-rw-r--r--src/frontend/parser.h46
4 files changed, 314 insertions, 38 deletions
diff --git a/src/frontend/lexer.c b/src/frontend/lexer.c
index 6dc348d..de8ff95 100644
--- a/src/frontend/lexer.c
+++ b/src/frontend/lexer.c
@@ -37,14 +37,26 @@ 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_OPEN_NORMAL,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_NORMAL,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_DOT,src->current_row,src->current_column);
if(check_and_move_if_on_word("]",sizeof("]")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("]")+1,sizeof("]")-1,KW_CLOSE_SQUARE,src->current_row,src->current_column);
if(check_and_move_if_on_word(";",sizeof(";")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof(";")+1,sizeof(";")-1,KW_SEMI_COLUMN,src->current_row,src->current_column);
if(check_and_move_if_on_word("|",sizeof("|")-1,src,0))
return get_token(src->src+src->where_in_src-sizeof("|")+1,sizeof("|")-1,KW_PIPE,src->current_row,src->current_column);
+ if(check_and_move_if_on_word("||",sizeof("||")-1,src,0))
+ return get_token(src->src+src->where_in_src-sizeof("||")+1,sizeof("||")-1,KW_OR,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_AND,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_NOT,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))
@@ -157,4 +169,10 @@ void push_token_into_map(struct token *token,struct Map *map,void *thing)
{
Map_Push(map,token->data,token->size,thing);
}
+void id_token_to_upper_case(struct token *token)
+{
+ size_t i;
+ for(i=0;i<token->size;++i)
+ token->data[i]=toupper(token->data[i]);
+}
#endif
diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h
index d102540..266beea 100644
--- a/src/frontend/lexer.h
+++ b/src/frontend/lexer.h
@@ -20,6 +20,8 @@ enum Keyword
KW_EOF,
KW_OPEN_SQUARE,
KW_CLOSE_SQUARE,
+ KW_OPEN_NORMAL,
+ KW_CLOSE_NORMAL,
KW_PIPE,
KW_SEMI_COLUMN,
KW_STARTING,
@@ -29,6 +31,10 @@ enum Keyword
KW_EXECUTE,
KW_TRANSITIONS,
KW_COMMA,
+ KW_DOT,
+ KW_AND,
+ KW_OR,
+ KW_NOT,
};
struct token
{
@@ -45,6 +51,7 @@ struct token* get_token(char *data,size_t size,enum Keyword type,size_t row,size
void skip_white_space(struct Source *src);
void push_token_into_map(struct token *token,struct Map *map,void *thing);
+void id_token_to_upper_case(struct token *token);
void delete_token(struct token *token);
diff --git a/src/frontend/parser.c b/src/frontend/parser.c
index 45752e7..a260622 100644
--- a/src/frontend/parser.c
+++ b/src/frontend/parser.c
@@ -13,17 +13,25 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
{
struct Queue *machines;
struct Map *hold_command_map;
+ struct Map *hold_machines_map;
struct AST_Machine *hold_machine;
machines=calloc(1,sizeof(struct Queue));
+
hold_command_map=malloc(sizeof(struct Map));
Map_Init(hold_command_map);
+ hold_machines_map=malloc(sizeof(struct Map));
+ Map_Init(hold_machines_map);
+
translation_data->hold_command_map=hold_command_map;
+ translation_data->hold_machines_map=hold_machines_map;
while(!get_and_check(translation_data,KW_EOF))
{
hold_machine=parse_machine(translation_data);
+ /*TODO check for repeated machine ids*/
+ Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
if(hold_machine)
{
Queue_Push(machines,hold_machine);
@@ -37,7 +45,7 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
return NULL;
}
}
- return get_ast_translation_unit(machines,hold_command_map);
+ return get_ast_translation_unit(machines,hold_command_map,hold_machines_map);
}
/*
* machine: 'machine' id '[' machine-inner ']' ';'
@@ -308,6 +316,10 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
{
push_parsing_error("there are no transitions",translation_data);
return NULL;
+ }else if(has_new_errors(translation_data))
+ {
+ push_parsing_error("in transition",translation_data);
+ return NULL;
}else
{
return get_ast_transitions(transitions);
@@ -328,44 +340,39 @@ struct AST_Transition* parse_transition(struct Translation_Data *translation_dat
if(get_and_check(translation_data,KW_FROM))
{
- if(get_kw(translation_data)==KW_ID)
+ hold_from=parse_expression(translation_data);
+ if(hold_from!=NULL)
{
- 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_and_check(translation_data,KW_TO))
+ if(get_kw(translation_data)==KW_ID)
{
- 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)
{
- 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_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ if(get_kw(translation_data)==KW_ID)
{
- 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)
{
- 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; }
+ 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 { return NULL; }
}
/*
@@ -402,7 +409,8 @@ struct AST_Command* parse_command(struct Translation_Data *translation_data)
if(get_kw(translation_data)==KW_STRING)
string=Queue_Pop(translation_data->tokens);
ret=get_ast_command(id,string);
- Map_Push(translation_data->hold_command_map,ret->argument->data,ret->argument->size,ret);
+ if(!Map_Check(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size))
+ Map_Push(translation_data->hold_command_map,ret->function_name->data,ret->function_name->size,ret);
return ret;
}else
@@ -441,6 +449,7 @@ struct AST_State* get_ast_state(struct token *id)
ret=malloc(sizeof(struct AST_State));
ret->name=id;
+
/*number is assigned in get_ast_states*/
return ret;
@@ -473,7 +482,9 @@ struct AST_States* get_ast_states(struct Queue *states)
while(states->size>0)
{
hold_state=Queue_Pop(states);
+ /*TODO check for redeclaration*/
Map_Push(ret->states_map,hold_state->name->data,hold_state->name->size,hold_state);
+
ret->states[states->size]=hold_state;
hold_state->number=states->size;
}
@@ -501,6 +512,7 @@ struct AST_Events* get_ast_events(struct Queue *events)
while(events->size>0)
{
hold_event=Queue_Pop(events);
+ /*TODO check for redeclaration*/
Map_Push(ret->events_map,hold_event->name->data,hold_event->name->size,hold_event);
ret->events[events->size]=hold_event;
}
@@ -510,7 +522,7 @@ struct AST_Events* get_ast_events(struct Queue *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* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline);
{
struct AST_Transition *ret;
ret=malloc(sizeof(struct AST_Transition));
@@ -556,6 +568,7 @@ struct AST_Machine* get_ast_machine(struct token *id,struct AST_States *states,s
ret->states=states;
ret->events=events;
ret->transitions=transitions;
+ ret->starting_state=starting_state;
return ret;
}
@@ -713,7 +726,7 @@ void delete_ast_translation_unit(struct AST_Translation_Unit *ast)
free(ast->used_commands_map);
free(ast);
}
-struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map)
+struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map)
{
struct AST_Translation_Unit *ret;
struct AST_Machine *hold_machine;
@@ -721,6 +734,7 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str
ret=malloc(sizeof(struct AST_Translation_Unit)+sizeof(struct AST_Machine *[machines->size]));
ret->type=AST_TYPE_TRANSLATION_UNIT;
ret->used_commands_map=command_map;
+ ret->machines_map=machines_map;
ret->number_of_machines=machines->size;
while(machines->size>0)
@@ -731,4 +745,201 @@ struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,str
return ret;
}
+/*
+ * expression: or-expression
+ */
+struct AST* parse_expression(struct Translation_Data *translation_data)
+{
+ return parse_or_expression(translation_data);
+}
+/*
+ * or-expression: and-expression [ || and-expression ]
+ */
+struct AST* parse_or_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_left_expression;
+ struct AST *hold_right_expression;
+
+ hold_left_expression=parse_and_expression(translation_data);
+ if(hold_left_expression==NULL)
+ return NULL;
+
+ if(get_and_check(translation_data,KW_OR))
+ {
+ hold_right_expression=parse_and_expression(translation_data);
+ if(hold_right_expression==NULL)
+ {
+ push_parsing_error("expected expression in right side of ||",translation_data);
+ delete_ast(hold_left_expression);
+ return NULL;
+ }
+ return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_OR);
+ }else
+ {
+ return hold_left_expression;
+ }
+
+}
+/*
+ * and-expression: not-expression [ && not-expression ]
+ */
+struct AST* parse_and_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_left_expression;
+ struct AST *hold_right_expression;
+
+ hold_left_expression=parse_not_expression(translation_data);
+ if(hold_left_expression==NULL)
+ return NULL;
+
+ if(get_and_check(translation_data,KW_AND))
+ {
+ hold_right_expression=parse_not_expression(translation_data);
+ if(hold_right_expression==NULL)
+ {
+ push_parsing_error("expected expression in right side of &&",translation_data);
+ delete_ast(hold_left_expression);
+ return NULL;
+ }
+ return (struct AST*)get_ast_binary_expression(left,right,AST_TYPE_OP_AND);
+ }else
+ {
+ return hold_left_expression;
+ }
+}
+/*
+ * not-expression: [!]primary-expression
+ */
+struct AST* parse_not_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_expression;
+ if(get_and_check(translation_data,KW_NOT))
+ {
+ hold_expression=parse_primary_expression(translation_data);
+ if(hold_expression!=NULL)
+ {
+ return get_ast_unary_expression(hold_expression,AST_TYPE_OP_NOT);
+ }else
+ {
+ push_parsing_error("in '!' expression",translation_data);
+ return NULL;
+ }
+ }
+ return parse_primary_expression(translation_data);
+}
+/*
+ * primary-expression: (expression) | id | id.id
+ */
+struct AST* parse_primary_expression(struct Translation_Data *translation_data)
+{
+ struct AST *hold_expression;
+ struct AST_Unchecked_State *hold_id1;
+ struct AST_Unchecked_State *hold_id2;
+
+ if(get_and_check(translation_data,KW_OPEN_NORMAL))
+ {
+ hold_expression=parse_expression(translation_data);
+ if(get_and_check(translation_data,KW_CLOSE_NORMAL))
+ {
+ return hold_expression;
+ }else
+ {
+ push_parsing_error("expected ')' in expression",translation_data);
+ delete_ast(hold_expression);
+ return NULL;
+ }
+
+ }else if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id1=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
+ if(get_and_check(translation_data,KW_DOT))
+ {
+ if(get_kw(translation_data)==KW_ID)
+ {
+ hold_id2=get_ast_unchecked_state(Queue_Pop(translation_data->tokens));
+ return get_ast_binary_expression(hold_id1,hold_id2,AST_TYPE_OP_SELECTOR);
+ }else
+ {
+ push_parsing_error("expected a state id in selector",translation_data);
+ delete_ast(hold_id1);
+ return NULL;
+ }
+ }else
+ {
+ return hold_id1;
+ }
+ }else
+ {
+ push_parsing_error("expected an expression",translation_data);
+ return NULL;
+ }
+}
+struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type)
+{
+ struct AST_Binary_Expression *ret;
+
+ ret=malloc(sizeof(struct AST_Binary_Expression));
+ ret->type=type;
+ ret->left=left;
+ ret->right=right;
+
+ return ret;
+}
+struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type)
+{
+
+ struct AST_Unary_Expression *ret;
+
+ ret=malloc(sizeof(struct AST_Unary_Expression));
+
+ ret->type=type;
+ ret->operand=operand;
+
+ return ret;
+}
+struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name)
+{
+ struct AST_Unchecked_State *ret;
+
+ ret=malloc(sizeof(struct AST_Unchecked_State));
+ ret->type=AST_TYPE_UNFINISHED_STATE;
+ ret->name=name;
+
+ return ret;
+}
+
+struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data)
+{
+ struct AST_State *ret;
+ ret=Map_Check(states->states_map,state->name->data,state->name->size);
+ delete_ast_unchecked_state(state);
+ if(ret==NULL)
+ {
+ push_parsing_error("undefined state",translation_data);
+ return NULL;
+ }else
+ {
+ return ret;
+ }
+}
+
+void delete_ast_binary_expression(struct AST_Binary_Expression *ast)
+{
+ if(ast->right)
+ delete_ast(ast->right);
+ if(ast->left)
+ delete_ast(ast->left);
+ free(ast);
+}
+void delete_ast_unary_expression(struct AST_Unary_Expression *ast)
+{
+ if(ast->operand)
+ delete_ast(ast->operand);
+ free(ast);
+}
+void delete_ast_unchecked_state(struct AST_Unchecked_State *ast)
+{
+ delete_token(ast->name);
+ free(ast);
+}
#endif
diff --git a/src/frontend/parser.h b/src/frontend/parser.h
index eaede84..74f2ed8 100644
--- a/src/frontend/parser.h
+++ b/src/frontend/parser.h
@@ -5,6 +5,9 @@
#include <assert.h>
#include <map.h>
+#define AS_BIN_EXPR_PTR(x) ((struct AST_Binary_Expression*)x)
+#define AS_UN_EXPR_PTR(x) ((struct AST_Unary_Expression*)x)
+#define AS_UNCK_EXPR_PTR(x) ((struct AST_Unchecked_State*)x)
enum AST_Type
{
AST_TYPE_TRANSLATION_UNIT,
@@ -17,6 +20,11 @@ enum AST_Type
AST_TYPE_TRANSITIONS,
AST_TYPE_COMMAND,
AST_TYPE_PIPELINE,
+ AST_TYPE_OP_AND,
+ AST_TYPE_OP_OR,
+ AST_TYPE_OP_NOT,
+ AST_TYPE_OP_SELECTOR,
+ AST_TYPE_UNFINISHED_STATE,
};
struct AST
{
@@ -48,7 +56,7 @@ struct AST_Events
struct AST_Transition
{
enum AST_Type type;
- struct AST_State *from;
+ struct AST *from;
struct AST_State *to;
struct AST_Event *event;
struct AST_Pipeline *pipeline;
@@ -75,6 +83,7 @@ struct AST_Machine
{
enum AST_Type type;
struct token *id;
+ struct AST_State *starting_state;
struct AST_States *states;
struct AST_Events *events;
struct AST_Transitions *transitions;
@@ -83,9 +92,26 @@ struct AST_Translation_Unit
{
enum AST_Type type;
struct Map *used_commands_map;
+ struct Map *machines_map;
size_t number_of_machines;
struct AST_Machine *machines[];
};
+struct AST_Binary_Expression
+{
+ enum AST_Type type;
+ struct AST *left;
+ struct AST *right;
+};
+struct AST_Unary_Expression
+{
+ enum AST_Type type;
+ struct AST *operand;
+};
+struct AST_Unchecked_State
+{
+ enum AST_Type type;
+ struct token *name;
+};
struct AST* parse_source(struct Translation_Data *translation_data);
@@ -102,18 +128,28 @@ 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* parse_expression(struct Translation_Data *translation_data);
+struct AST* parse_or_expression(struct Translation_Data *translation_data);
+struct AST* parse_and_expression(struct Translation_Data *translation_data);
+struct AST* parse_not_expression(struct Translation_Data *translation_data);
+struct AST* parse_primary_expression(struct Translation_Data *translation_data);
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_Transition* get_ast_transition(struct AST *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);
-struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map);
+struct AST_Translation_Unit* get_ast_translation_unit(struct Queue *machines,struct Map *command_map,struct Map *machines_map);
+
+struct AST_Binary_Expression* get_ast_binary_expression(struct AST *left,struct AST *right,enum AST_Type type);
+struct AST_Unary_Expression* get_ast_unary_expression(struct AST *operand,enum AST_Type type);
+struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name);
+struct AST_State* ast_check_state(struct AST_Unchecked_State *state,struct AST_States *states,struct Translation_Data *translation_data);
void delete_ast(struct AST* ast);
void delete_ast_event(struct AST_Event* ast);
@@ -127,6 +163,10 @@ void delete_ast_machine(struct AST_Machine* ast);
void delete_ast_transitions(struct AST_Transitions* ast);
void delete_ast_translation_unit(struct AST_Translation_Unit *ast);
+void delete_ast_binary_expression(struct AST_Binary_Expression *ast);
+void delete_ast_unary_expression(struct AST_Unary_Expression *ast);
+void delete_ast_unchecked_state(struct AST_Unchecked_State *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);