aboutsummaryrefslogtreecommitdiffstats
path: root/src/frontend/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/parser.c')
-rw-r--r--src/frontend/parser.c281
1 files changed, 246 insertions, 35 deletions
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