DSM: "for (x in array)" and "for (k,v in struct)"

Development sponsored by TelTech Systems Inc.
sayer/1.4-spce2.6
Stefan Sayer 16 years ago
parent b12da91f64
commit d90e76a7d3

@ -26,6 +26,7 @@
*/
#include "DSMChartReader.h"
#include "log.h"
#include "AmUtils.h"
#include <dlfcn.h> // dlopen & friends
@ -149,6 +150,39 @@ DSMFunction* DSMChartReader::functionFromToken(const string& str) {
return NULL;
}
bool DSMChartReader::forFromToken(DSMArrayFor& af, const string& token) {
string forhdr = token;
if (forhdr.length() < 2 || forhdr[0] != '(' || forhdr[forhdr.length()-1] != ')') {
ERROR("syntax error in 'for %s': expected 'for (x in array)'\n",
forhdr.c_str());
return false;
}
forhdr = forhdr.substr(1, forhdr.length()-2);
// q&d
vector<string> forh_v = explode(forhdr, " in ");
if (forh_v.size() != 2) {
ERROR("syntax error in 'for %s': expected 'for (x in array)' "
"or 'for (k,v in struct)'\n",
forhdr.c_str());
return false;
}
af.array_struct = forh_v[1];
vector<string> kv = explode(forh_v[0], ",");
if (kv.size() == 2) {
af.k = kv[0];
af.v = kv[1];
DBG("for (%s,%s in %s) {\n", af.k.c_str(), af.v.c_str(), af.array_struct.c_str());
} else {
af.k = forh_v[0];
DBG("for (%s in %s) {\n", af.k.c_str(), af.array_struct.c_str());
}
return true;
}
DSMCondition* DSMChartReader::conditionFromToken(const string& str, bool invert) {
for (vector<DSMModule*>::iterator it=
mods.begin(); it!= mods.end(); it++) {
@ -245,7 +279,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
stack.push_back(new DSMTransition());
continue;
}
if (stack.empty()) {
if (token == ";")
continue;
@ -288,27 +322,27 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
DSMConditionTree* ct = dynamic_cast<DSMConditionTree*>(stack_top);
if (ct) {
if (token == "[") {
stack.push_back(new DSMConditionList());
continue;
}
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<ActionList*>(&(*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;
}
if (token == ";") {
stack.pop_back();
ActionList* al = dynamic_cast<ActionList*>(&(*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<State*>(stack_top);
@ -405,6 +439,26 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
return false;
}
t->actions = al->actions;
} else if (al->al_type == ActionList::AL_for) {
DSMArrayFor* af = dynamic_cast<DSMArrayFor*>(&(*stack.back()));
if (!af) {
ERROR("no DSMArrayFor for action list\n");
delete al;
return false;
}
af->actions = al->actions;
stack.pop_back();
ActionList* b_al = dynamic_cast<ActionList*>(&(*stack.back()));
if (!b_al) {
ERROR("internal error: no ActionList for 'for'\n");
return false;
}
b_al->actions.push_back(af);
DBG("} // end for (%s%s in %s) {\n",
af->k.c_str(), af->v.empty() ? "" : (","+af->v).c_str(),
af->array_struct.c_str());
} else {
ERROR("internal: unknown transition list type\n");
}
@ -416,12 +470,23 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
//token is condition tree
stack.push_back(new DSMConditionTree());
continue;
} else if (token.substr(0, 3) == "for") {
// token is for loop
DSMArrayFor* af = new DSMArrayFor();
if (token.length() > 3) {
if (!forFromToken(*af, token.substr(3)))
return false;
}
stack.push_back(af);
continue;
} else {
DSMFunction* f = functionFromToken(token);
if (f) {
DBG("adding actions from function '%s'\n", f->name.c_str());
DBG("al.size is %zd before", al->actions.size());
for (vector<DSMElement*>::iterator it=f->actions.begin(); it != f->actions.end(); it++) {
for (vector<DSMElement*>::iterator it=f->actions.begin();
it != f->actions.end(); it++) {
DSMElement* a = *it;
owner->transferElem(a);
al->actions.push_back(a);
@ -553,6 +618,31 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
}
continue;
}
DSMArrayFor* af = dynamic_cast<DSMArrayFor*>(stack_top);
if (af) {
if (af->array_struct.length() || af->k.length()) {
// expecting body
if (token == "}") {
DBG("close for\n");
ERROR("sounds wrong!!!\n");
stack.pop_back();
continue;
}
if (token == "{") {
// start action list for 'for'
stack.push_back(new ActionList(ActionList::AL_for));
continue;
}
} else {
if (!forFromToken(*af, token))
return false;
}
continue;
}
}
for (vector<DSMModule*>::iterator it=

@ -59,8 +59,9 @@ class ActionList : public DSMElement {
AL_exit,
AL_trans,
AL_if,
AL_else,
AL_func
AL_else,
AL_func,
AL_for
};
AL_type al_type;
@ -87,6 +88,7 @@ class DSMChartReader {
DSMFunction* functionFromToken(const string& str);
DSMAction* actionFromToken(const string& str);
DSMCondition* conditionFromToken(const string& str, bool invert);
bool forFromToken(DSMArrayFor& af, const string& token);
bool importModule(const string& mod_cmd, const string& mod_path);
vector<DSMModule*> mods;

@ -264,6 +264,7 @@ bool DSMStateEngine::runactions(vector<DSMElement*>::iterator from,
default: break;
}
}
continue;
}
DSMConditionTree* cond_tree = dynamic_cast<DSMConditionTree*>(*it);
@ -285,8 +286,104 @@ bool DSMStateEngine::runactions(vector<DSMElement*>::iterator from,
sess, sc_sess, event, event_params, is_consumed))
return true;
}
continue;
}
DSMArrayFor* array_for = dynamic_cast<DSMArrayFor*>(*it);
if (array_for) {
DBG("running for (%s%s in %s) {\n",
array_for->k.c_str(), array_for->v.empty() ? "" : (","+array_for->v).c_str(),
array_for->array_struct.c_str());
string array_name = array_for->array_struct;
string k_name = array_for->k;
string v_name = array_for->v;
if (!array_name.length() || !k_name.length()) {
WARN("empty array or counter name in for\n");
continue;
}
if (array_name[0] == '$') array_name.erase(0, 1);
if (k_name[0] == '$') k_name.erase(0, 1);
bool is_kv = !v_name.empty();
if (is_kv && v_name[0] == '$') v_name.erase(0, 1);
vector<pair<string, string> > cnt_values;
// get the counter values
if (is_kv) {
VarMapT::iterator lb = sc_sess->var.lower_bound(array_name);
while (lb != sc_sess->var.end()) {
if ((lb->first.length() < array_name.length()) ||
strncmp(lb->first.c_str(), array_name.c_str(), array_name.length()))
break;
string varname = lb->first.substr(array_name.length()+1);
string valname = lb->second;
cnt_values.push_back(make_pair(varname, valname));
DBG(" '%s,%s'\n", varname.c_str(), valname.c_str());
lb++;
}
} else {
unsigned int a_index = 0;
while (true) {
VarMapT::iterator v = sc_sess->var.find(array_name+"["+int2str(a_index)+"]");
if (v == sc_sess->var.end())
break;
cnt_values.push_back(make_pair(v->second, ""));
DBG(" '%s'\n", v->second.c_str());
a_index++;
}
}
// save counter
VarMapT::iterator c_it = sc_sess->var.find(k_name);
bool k_exists = c_it != sc_sess->var.end();
string k_save = k_exists ? c_it->second : string("");
bool v_exists = false; string v_save;
if (is_kv) {
c_it = sc_sess->var.find(v_name);
v_exists = c_it != sc_sess->var.end();
if (v_exists)
v_save = c_it->second;
}
// run the loop
DBG("running for loop with %zd items\n", cnt_values.size());
for (vector<pair<string, string> >::iterator f_it=
cnt_values.begin(); f_it != cnt_values.end(); f_it++) {
if (is_kv) {
DBG("setting $%s=%s, $%s=%s\n", k_name.c_str(), f_it->first.c_str(),
v_name.c_str(), f_it->second.c_str());
sc_sess->var[k_name] = f_it->first;
sc_sess->var[v_name] = f_it->second;
} else {
DBG("setting $%s=%s\n", k_name.c_str(), f_it->first.c_str());
sc_sess->var[k_name] = f_it->first;
}
runactions(array_for->actions.begin(), array_for->actions.end(),
sess, sc_sess, event, event_params, is_consumed);
}
// restore the counter[s]
if (k_exists)
sc_sess->var[k_name] = k_save;
else
sc_sess->var.erase(k_name);
if (is_kv) {
if (v_exists)
sc_sess->var[v_name] = v_save;
else
sc_sess->var.erase(v_name);
}
continue;
}
ERROR("DSMElement typenot understood\n");
}
return false;
}

@ -177,6 +177,15 @@ class DSMFunction
vector<DSMElement*> actions;
};
class DSMArrayFor
: public DSMElement {
public:
string k; // for(k in array)
string v; // if set, for(k,v in struct)
string array_struct; // array or struct name
vector<DSMElement*> actions;
};
class DSMModule;
class DSMStateDiagram {

Loading…
Cancel
Save