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.c159
1 files changed, 119 insertions, 40 deletions
diff --git a/src/frontend/parser.c b/src/frontend/parser.c
index fa692f5..7af7af2 100644
--- a/src/frontend/parser.c
+++ b/src/frontend/parser.c
@@ -30,9 +30,9 @@ struct AST_Translation_Unit* parse_translation_unit(struct Translation_Data *tra
{
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)
{
+ Map_Push(hold_machines_map,hold_machine->id->data,hold_machine->id->size,hold_machine);
Queue_Push(machines,hold_machine);
}
else
@@ -307,8 +307,6 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
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)
@@ -331,49 +329,106 @@ struct AST_Transitions* parse_transitions_inner(struct Translation_Data *transla
struct AST_Transition* parse_transition(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
{
struct AST_Transition *ret;
- struct AST *hold_from;
+ struct AST_State *hold_from;
struct AST_State *hold_to;
struct AST_Event *hold_event;
- struct AST_Pipeline *hold_pipeline=NULL;
+ struct AST *hold_statement=NULL;
struct token *hold_token;
if(get_and_check(translation_data,KW_FROM))
{
- hold_from=parse_expression(translation_data);
- if(hold_from!=NULL)
+ if(get_kw(translation_data)==KW_ID)
{
- if(get_and_check(translation_data,KW_TO))
+ hold_token=Queue_Pop(translation_data->tokens);
+ hold_from=Map_Check(states->states_map,hold_token->data,hold_token->size);
+ if(hold_from!=NULL)
{
- if(get_kw(translation_data)==KW_ID)
+ if(get_and_check(translation_data,KW_TO))
{
- 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_kw(translation_data)==KW_ID)
{
- if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
+ 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_kw(translation_data)==KW_ID)
+ if(get_and_check(translation_data,KW_ON) && get_and_check(translation_data,KW_EVENT) )
{
- 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_kw(translation_data)==KW_ID)
{
- 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; }
+ 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_SEMI_COLUMN) && (hold_statement=parse_statement(translation_data,states,events))==NULL)
+ { push_parsing_error("in statement of transition",translation_data); return NULL; }
+
+ /*GOAL!!!!!*/
+ return get_ast_transition(hold_from,hold_to,hold_event,hold_statement);
+ }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 state id in from field",translation_data); return NULL; }
}else { return NULL; }
}
+
+/*
+ * statement : 'execute' pipeline ; | 'if' expression statement [ else statement ]
+ */
+struct AST* parse_statement(struct Translation_Data *translation_data,struct AST_States *states,struct AST_Events *events)
+{
+ struct AST *hold_expression;
+ struct AST *hold_body;
+ struct AST *hold_else=NULL;
+
+ if(get_and_check(translation_data,KW_EXECUTE))
+ {
+ hold_body=(struct AST*)parse_pipeline(translation_data);
+ if(get_and_check(translation_data,KW_SEMI_COLUMN))
+ {
+ return hold_body;
+ }else
+ {
+ push_parsing_error("expected ';' at the end of pipeline",translation_data);
+ delete_ast(hold_body);
+ return NULL;
+ }
+ }else if(get_and_check(translation_data,KW_IF))
+ {
+ hold_expression=parse_expression(translation_data);
+ hold_body=parse_statement(translation_data,states,events);
+ if(hold_body)
+ {
+ if(get_and_check(translation_data,KW_ELSE))
+ {
+ hold_else=parse_statement(translation_data,states,events);
+ if(hold_else==NULL)
+ {
+ push_parsing_error("expected a statement after else",translation_data);
+ delete_ast(hold_expression);
+ delete_ast(hold_body);
+ return NULL;
+ }
+ }
+ return (struct AST*)get_ast_if_statement(hold_expression,hold_body,hold_else);
+ }else
+ {
+ push_parsing_error("expected body statement in if",translation_data);
+ if(hold_expression)
+ delete_ast(hold_expression);
+ return NULL;
+ }
+ }else
+ {
+ return NULL;
+ }
+}
/*
* pipeline: [ command ( | command )* ]
*
@@ -523,7 +578,7 @@ struct AST_Events* get_ast_events(struct Queue *events)
return ret;
}
-struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,struct AST_Event *event,struct AST_Pipeline *pipeline)
+struct AST_Transition* get_ast_transition(struct AST_State *from,struct AST_State *to,struct AST_Event *event,struct AST *statement)
{
struct AST_Transition *ret;
ret=malloc(sizeof(struct AST_Transition));
@@ -531,7 +586,7 @@ struct AST_Transition* get_ast_transition(struct AST *from,struct AST_State *to,
ret->from=from;
ret->to=to;
ret->event=event;
- ret->pipeline=pipeline;
+ ret->statement=statement;
return ret;
}
@@ -632,7 +687,9 @@ void delete_ast(struct AST* ast)
case AST_TYPE_UNFINISHED_STATE:
delete_ast_unchecked_state((struct AST_Unchecked_State*)ast);
break;
-
+ case AST_TYPE_IF:
+ delete_ast_if_statement((struct AST_If_Statement*)ast);
+ break;
}
}
void delete_ast_event(struct AST_Event* ast)
@@ -660,8 +717,8 @@ void delete_ast_events(struct AST_Events* ast)
void delete_ast_transition(struct AST_Transition* ast)
{
if(ast==NULL)return;
- if(ast->pipeline!=NULL)
- delete_ast_pipeline(ast->pipeline);
+ if(ast->statement!=NULL)
+ delete_ast(ast->statement);
free(ast);
}
void delete_ast_command(struct AST_Command* ast)
@@ -842,7 +899,7 @@ struct AST* parse_not_expression(struct Translation_Data *translation_data)
return parse_primary_expression(translation_data);
}
/*
- * primary-expression: (expression) | id | id.id
+ * primary-expression: (expression) | id.id
*/
struct AST* parse_primary_expression(struct Translation_Data *translation_data)
{
@@ -880,7 +937,9 @@ struct AST* parse_primary_expression(struct Translation_Data *translation_data)
}
}else
{
- return (struct AST*)hold_id1;
+ delete_ast((struct AST*)hold_id1);
+ push_parsing_error("expected a selector",translation_data);
+ return NULL;
}
}else
{
@@ -921,18 +980,31 @@ struct AST_Unchecked_State* get_ast_unchecked_state(struct token *name)
return ret;
}
+struct AST_If_Statement* get_ast_if_statement(struct AST *condition,struct AST *body,struct AST *else_statement)
+{
+ struct AST_If_Statement *ret;
+
+ ret=malloc(sizeof(struct AST_If_Statement));
+ ret->type=AST_TYPE_IF;
+ ret->condition=condition;
+ ret->body=body;
+ ret->else_statement=else_statement;
+
+ 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);
+ push_error_with_token("undefined state",state->name,translation_data);
+ delete_ast_unchecked_state(state);
return NULL;
}else
{
+ delete_ast_unchecked_state(state);
return ret;
}
}
@@ -956,4 +1028,11 @@ void delete_ast_unchecked_state(struct AST_Unchecked_State *ast)
delete_token(ast->name);
free(ast);
}
+void delete_ast_if_statement(struct AST_If_Statement *ast)
+{
+ delete_ast(ast->condition);
+ delete_ast(ast->body);
+ if(ast->else_statement)
+ delete_ast(ast->else_statement);
+}
#endif