From f4b8287436aeb0018ee70b3dc32241b212bda5e9 Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Sat, 4 Dec 2010 06:14:34 +0000 Subject: [PATCH] initial support for if blocks (no else) --- apps/dsm/DSMChartReader.cpp | 237 +++++++++++++++++++++++------------- apps/dsm/DSMChartReader.h | 6 +- apps/dsm/DSMStateEngine.cpp | 94 +++++++++----- apps/dsm/DSMStateEngine.h | 19 ++- 4 files changed, 229 insertions(+), 127 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 45b0a7ba..90c52f3e 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -43,7 +43,7 @@ bool DSMChartReader::is_wsp(const char c) { } bool DSMChartReader::is_snt(const char c) { - return c== ';' || c == '{' || c == '}'; + return c== ';' || c == '{' || c == '}' || c == '[' || c == ']'; } string DSMChartReader::getToken(string str, size_t& pos) { @@ -219,16 +219,44 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, stack.push_back(new DSMTransition()); continue; } - + if (stack.empty()) { if (token == ";") - continue; + continue; ERROR("Without context I do not understand '%s'\n", token.c_str()); return false; } DSMElement* stack_top = &(*stack.back()); + DSMConditionTree* ct = dynamic_cast(stack_top); + if (ct) { + if (token == "[") { + stack.push_back(new DSMConditionList()); + continue; + } + if (token == "{") { + stack.push_back(new ActionList(ActionList::AL_if)); + continue; + } + if (token == ";") { + stack.pop_back(); + ActionList* al = dynamic_cast(&(*stack.back())); + if (al) { + owner->transferElem(ct); + al->actions.push_back(ct); + DBG("Added DSMConditionTree to ActionList\n"); + } else { + ERROR("no ActionList for DSMConditionTree\n"); + delete al; + return false; + } + continue; + } + } + + + State* state = dynamic_cast(stack_top); if (state) { if (!state->name.length()) { @@ -237,6 +265,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } if (token == "enter") { + DBG("adding 'enter' actions for state '%s'\n", state->name.c_str()); stack.push_back(new ActionList(ActionList::AL_enter)); continue; } @@ -261,116 +290,150 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } - ActionList* al = dynamic_cast(stack_top); - if (al) { - if (token == ";") { - continue; + ActionList* al = dynamic_cast(stack_top); + if (al) { + if (token == ";") { + continue; + } + if (token == "{") { + continue; + } + + if ((token == "}") || (token == "->")) { + stack.pop_back(); + if (stack.empty()) { + ERROR("no item for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_if || + al->al_type == ActionList::AL_else) { + DSMConditionTree* ct = dynamic_cast(&(*stack.back())); + if (!ct) { + ERROR("no DSMConditionTree for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_if) { + ct->run_if_true = al->actions; + } else if (al->al_type == ActionList::AL_else) { + ct->run_if_false = al->actions; + } + } else if (al->al_type == ActionList::AL_enter || + al->al_type == ActionList::AL_exit) { + State* s = dynamic_cast(&(*stack.back())); + if (!s) { + ERROR("no State for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_enter) { + s->pre_actions = al->actions; + } else if (al->al_type == ActionList::AL_exit) { + s->post_actions = al->actions; + } + } else if (al->al_type == ActionList::AL_trans) { + DSMTransition* t = dynamic_cast(&(*stack.back())); + if (!t) { + ERROR("no DSMTransition for action list\n"); + delete al; + return false; + } + t->actions = al->actions; + } else { + ERROR("internal: unknown transition list type\n"); + } + delete al; + continue; } - if (token == "{") { - continue; - } - if ((token == "}") || (token == "->")) { - stack.pop_back(); - if (stack.empty()) { - ERROR("no item for action list\n"); - delete al; - return false; - } - - if (al->al_type == ActionList::AL_enter || - al->al_type == ActionList::AL_exit) { - State* s = dynamic_cast(&(*stack.back())); - if (!s) { - ERROR("no State for action list\n"); - delete al; - return false; - } - if (al->al_type == ActionList::AL_enter) - s->pre_actions = al->actions; - else if (al->al_type == ActionList::AL_exit) - s->post_actions = al->actions; - } else if (al->al_type == ActionList::AL_trans) { - DSMTransition* t = dynamic_cast(&(*stack.back())); - if (!t) { - ERROR("no DSMTransition for action list\n"); - delete al; - return false; - } - t->actions = al->actions; - } else { - ERROR("internal: unknown transition list type\n"); - } - delete al; - continue; - } - - // token is action - // DBG("adding action '%s'\n", token.c_str()); - DSMAction* a = actionFromToken(token); - if (!a) - return false; - owner->transferElem(a); - al->actions.push_back(a); - continue; - } + + if (token == "if") { + //token is condition tree + stack.push_back(new DSMConditionTree()); + continue; + } else { + // token is action + DBG("adding action '%s'\n", token.c_str()); + + DSMAction* a = actionFromToken(token); + if (!a) + return false; + owner->transferElem(a); + al->actions.push_back(a); + continue; + } + } + DSMConditionList* cl = dynamic_cast(stack_top); if (cl) { if (token == ";") - continue; + continue; if ((token == "{") || (token == "}")) { - // readability - continue; + // readability + continue; } - if ((token == "/") || (token == "->")) { - // end of condition list - stack.pop_back(); - if (stack.empty()) { - ERROR("no transition to apply conditions to\n"); - delete cl; - return false; - } - DSMTransition* tr = dynamic_cast(&(*stack.back())); - if (!tr) { - ERROR("no transition to apply conditions to\n"); - delete cl; - return false; - } - - tr->precond = cl->conditions; - tr->is_exception = cl->is_exception; - delete cl; - - // start AL_trans action list - if (token == "/") { - stack.push_back(new ActionList(ActionList::AL_trans)); - } - continue; + if ((token == "/") || (token == "->") || (token == "]")) { + // end of condition list + stack.pop_back(); + if (stack.empty()) { + ERROR("nothing to apply conditions to\n"); + delete cl; + return false; + } + + DSMElement* el = &(*stack.back()); + + DSMTransition* tr = dynamic_cast(el); + DSMConditionTree* ct = dynamic_cast(el); + if (tr) { + tr->precond = cl->conditions; + tr->is_exception = cl->is_exception; + } else if (ct) { + ct->conditions = cl->conditions; + ct->is_exception = cl->is_exception; + } else { + ERROR("no transition or condition list to apply conditions to\n"); + delete cl; + return false; + } + + delete cl; + + // start AL_trans action list + if (token == "/") { + stack.push_back(new ActionList(ActionList::AL_trans)); + } + continue; } if (token == "not") { - cl->invert_next = !cl->invert_next; - continue; + cl->invert_next = !cl->invert_next; + continue; } if (token == "exception") { - cl->is_exception = true; - continue; + cl->is_exception = true; + continue; } - // DBG("new condition: '%s'\n", token.c_str()); + DBG("new condition: '%s'\n", token.c_str()); DSMCondition* c = conditionFromToken(token, cl->invert_next); cl->invert_next = false; if (!c) - return false; + return false; owner->transferElem(c); cl->conditions.push_back(c); continue; } + DSMTransition* tr = dynamic_cast(stack_top); if (tr) { if (!tr->name.length()) { diff --git a/apps/dsm/DSMChartReader.h b/apps/dsm/DSMChartReader.h index 1f663de6..b6dd48bc 100644 --- a/apps/dsm/DSMChartReader.h +++ b/apps/dsm/DSMChartReader.h @@ -57,7 +57,9 @@ class ActionList : public DSMElement { enum AL_type { AL_enter, AL_exit, - AL_trans + AL_trans, + AL_if, + AL_else }; AL_type al_type; @@ -65,7 +67,7 @@ class ActionList : public DSMElement { ActionList(AL_type al_type) : al_type(al_type) { } - vector actions; + vector actions; }; struct DSMConditionList : public DSMElement { diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 4a17593a..053143d7 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -46,11 +46,11 @@ DSMStateDiagram::~DSMStateDiagram() { void DSMStateDiagram::addState(const State& state, bool is_initial) { DBG("adding state '%s'\n", state.name.c_str()); - for (vector::const_iterator it= + for (vector::const_iterator it= state.pre_actions.begin(); it != state.pre_actions.end(); it++) { DBG(" pre-action '%s'\n", (*it)->name.c_str()); } - for (vector::const_iterator it= + for (vector::const_iterator it= state.post_actions.begin(); it != state.post_actions.end(); it++) { DBG(" post-action '%s'\n", (*it)->name.c_str()); } @@ -75,7 +75,7 @@ bool DSMStateDiagram::addTransition(const DSMTransition& trans) { DBG(" DSMCondition %s'%s'\n", (*it)->invert?"not ":"", (*it)->name.c_str()); } - for (vector::const_iterator it= + for (vector::const_iterator it= trans.actions.begin(); it != trans.actions.end(); it++) { DBG(" Action '%s'\n", (*it)->name.c_str()); } @@ -224,42 +224,70 @@ void DSMStateEngine::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { (*it)->onBeforeDestroy(sc_sess, sess); } -bool DSMStateEngine::runactions(vector::iterator from, - vector::iterator to, +bool DSMStateEngine::runactions(vector::iterator from, + vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed) { // DBG("running %zd actions\n", to - from); - for (vector::iterator it=from; it != to; it++) { - DBG("executing '%s'\n", (*it)->name.c_str()); - if ((*it)->execute(sess, sc_sess, event, event_params)) { - string se_modifier; - switch ((*it)->getSEAction(se_modifier, - sess, sc_sess, event, event_params)) { - case DSMAction::Repost: - is_consumed = false; - break; - case DSMAction::Jump: - DBG("jumping to %s\n", se_modifier.c_str()); - if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } break; - case DSMAction::Call: - DBG("calling %s\n", se_modifier.c_str()); - if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } break; - case DSMAction::Return: - if (returnDiag(sess, sc_sess)) { - //is_consumed = false; - return true; - } break; - default: break; + for (vector::iterator it=from; it != to; it++) { + + DSMConditionTree* cond_tree = dynamic_cast(*it); + if (cond_tree) { + DBG("checking conditions\n"); + vector::iterator con=cond_tree->conditions.begin(); + while (con!=cond_tree->conditions.end()) { + if (!(*con)->_match(sess, sc_sess, event, event_params)) + break; + con++; + } + if (con == cond_tree->conditions.end()) { + DBG("condition tree matched.\n"); + if (runactions(cond_tree->run_if_true.begin(), cond_tree->run_if_true.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; + } else { + if(runactions(cond_tree->run_if_false.begin(), cond_tree->run_if_false.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; } } + + DSMAction* dsm_act = dynamic_cast(*it); + + if (dsm_act) { + DBG("executing '%s'\n", (dsm_act)->name.c_str()); + if ((dsm_act)->execute(sess, sc_sess, event, event_params)) { + string se_modifier; + switch ((dsm_act)->getSEAction(se_modifier, + sess, sc_sess, event, event_params)) { + case DSMAction::Repost: + is_consumed = false; + break; + case DSMAction::Jump: + DBG("jumping to %s\n", se_modifier.c_str()); + if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Call: + DBG("calling %s\n", se_modifier.c_str()); + if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Return: + if (returnDiag(sess, sc_sess)) { + //is_consumed = false; + return true; + } + break; + default: break; + } + } + } } - return false; } diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index fc1d8dfa..fde30f9d 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -141,8 +141,8 @@ class State public: State(); ~State(); - vector pre_actions; - vector post_actions; + vector pre_actions; + vector post_actions; vector transitions; }; @@ -154,13 +154,22 @@ class DSMTransition ~DSMTransition(); vector precond; - vector actions; + vector actions; string from_state; string to_state; bool is_exception; }; +class DSMConditionTree +: public DSMElement { + public: + vector conditions; + vector run_if_true; + vector run_if_false; + bool is_exception; +}; + class DSMModule; class DSMStateDiagram { @@ -224,8 +233,8 @@ class DSMStateEngine { DSMCondition::EventType event, map* event_params); bool returnDiag(AmSession* sess, DSMSession* sc_sess); - bool runactions(vector::iterator from, - vector::iterator to, + bool runactions(vector::iterator from, + vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed);