summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-04-11 07:58:48 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-04-11 07:58:48 (GMT)
commit71c334bf4e35559496feac3f3cf00b72ceb88812 (patch)
tree859f78af51c8e929559a53d70492035ef3fad862
parent5180e4666a314db36a15d953fdfa38af4f285758 (diff)
downloaduscxml-71c334bf4e35559496feac3f3cf00b72ceb88812.zip
uscxml-71c334bf4e35559496feac3f3cf00b72ceb88812.tar.gz
uscxml-71c334bf4e35559496feac3f3cf00b72ceb88812.tar.bz2
More work on promela DM
changed const of Data subscript operator and introduced at(key) and item(index)
-rw-r--r--src/uscxml/Factory.cpp17
-rw-r--r--src/uscxml/Factory.h3
-rw-r--r--src/uscxml/Message.h37
-rw-r--r--src/uscxml/debug/Breakpoint.cpp46
-rw-r--r--src/uscxml/debug/DebugSession.cpp10
-rw-r--r--src/uscxml/debug/DebuggerServlet.cpp66
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp92
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.h2
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaParser.cpp43
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaParser.h5
-rw-r--r--src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp4
-rw-r--r--src/uscxml/plugins/datamodel/promela/parser/promela.ypp4
-rw-r--r--src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp10
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp8
-rw-r--r--test/samples/uscxml/promela/test-simple-promela.scxml6
-rw-r--r--test/src/test-promela-parser.cpp1
16 files changed, 240 insertions, 114 deletions
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index a66b024..5f3d172 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -607,6 +607,23 @@ void EventHandlerImpl::returnEvent(Event& event) {
_interpreter->receive(event);
}
+void DataModelImpl::throwErrorExecution(const std::string& cause) {
+ uscxml::Event exc;
+ exc.data.compound["exception"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
+ exc.name = "error.execution";
+ exc.eventType = uscxml::Event::PLATFORM;
+ throw exc;
+}
+
+void DataModelImpl::throwErrorPlatform(const std::string& cause) {
+ uscxml::Event exc;
+ exc.data.compound["exception"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
+ exc.name = "error.platform";
+ exc.eventType = uscxml::Event::PLATFORM;
+ throw exc;
+}
+
+
Factory* Factory::_instance = NULL;
std::string Factory::pluginPath;
} \ No newline at end of file
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index 9997b15..14325f1 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -318,6 +318,9 @@ public:
virtual std::string andExpressions(std::list<std::string>) { return ""; }
+ static void throwErrorExecution(const std::string& cause);
+ static void throwErrorPlatform(const std::string& cause);
+
// we need it public for various static functions
InterpreterImpl* _interpreter;
};
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index f61cd1d..afc30ad 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -110,23 +110,50 @@ public:
return (atom.length() > 0 || !compound.empty() || !array.empty() || binary || node);
}
+ void merge(const Data& other);
+
bool hasKey(const std::string& key) const {
return (!compound.empty() && compound.find(key) != compound.end());
}
- const Data operator[](const std::string& key) const {
+ Data& operator[](const std::string& key) {
return operator[](key.c_str());
}
-
- void merge(const Data& other);
- const Data operator[](const char* key) const {
+ Data& operator[](const char* key) {
+ return compound[key];
+ }
+
+ Data& operator[](const size_t index) {
+ while(array.size() < index) {
+ array.push_back(Data("", Data::VERBATIM));
+ }
+ std::list<Data>::iterator arrayIter = array.begin();
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+
+ const Data at(const std::string& key) const {
+ return at(key.c_str());
+ }
+
+ const Data at(const char* key) const {
if (hasKey(key))
return compound.at(key);
Data data;
return data;
}
-
+
+ const Data item(const size_t index) const {
+ if (array.size() < index) {
+ std::list<Data>::const_iterator arrayIter;
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+ Data data;
+ return data;
+ }
+
bool operator==(const Data &other) const {
if (other.atom.size() != atom.size())
return false;
diff --git a/src/uscxml/debug/Breakpoint.cpp b/src/uscxml/debug/Breakpoint.cpp
index df5dd61..0001127 100644
--- a/src/uscxml/debug/Breakpoint.cpp
+++ b/src/uscxml/debug/Breakpoint.cpp
@@ -31,73 +31,73 @@ Breakpoint::Breakpoint(const Data& data) {
if (data.hasKey("when")) {
if (false) {
- } else if (data["when"].atom == "before") {
+ } else if (data.at("when").atom == "before") {
when = BEFORE;
- } else if (data["when"].atom == "after") {
+ } else if (data.at("when").atom == "after") {
when = AFTER;
- } else if (data["when"].atom == "on") {
+ } else if (data.at("when").atom == "on") {
when = ON;
}
}
if (data.hasKey("action")) {
if (false) {
- } else if (data["action"].atom == "enter") {
+ } else if (data.at("action").atom == "enter") {
action = ENTER;
- } else if (data["action"].atom == "exit") {
+ } else if (data.at("action").atom == "exit") {
action = EXIT;
- } else if (data["action"].atom == "invoke") {
+ } else if (data.at("action").atom == "invoke") {
action = INVOKE;
- } else if (data["action"].atom == "cancel") {
+ } else if (data.at("action").atom == "cancel") {
action = UNINVOKE;
}
}
if (data.hasKey("subject")) {
if (false) {
- } else if (data["subject"].atom == "state") {
+ } else if (data.at("subject").atom == "state") {
subject = STATE;
- } else if (data["subject"].atom == "transition") {
+ } else if (data.at("subject").atom == "transition") {
subject = TRANSITION;
- } else if (data["subject"].atom == "stable") {
+ } else if (data.at("subject").atom == "stable") {
subject = STABLE;
- } else if (data["subject"].atom == "microstep") {
+ } else if (data.at("subject").atom == "microstep") {
subject = MICROSTEP;
- } else if (data["subject"].atom == "event") {
+ } else if (data.at("subject").atom == "event") {
subject = EVENT;
- } else if (data["subject"].atom == "invoker") {
+ } else if (data.at("subject").atom == "invoker") {
subject = INVOKER;
- } else if (data["subject"].atom == "executable") {
+ } else if (data.at("subject").atom == "executable") {
subject = EXECUTABLE;
}
}
if (data.hasKey("condition"))
- condition = data["condition"].atom;
+ condition = data.at("condition").atom;
if (data.hasKey("invokeId"))
- invokeId = data["invokeId"].atom;
+ invokeId = data.at("invokeId").atom;
if (data.hasKey("invokeType"))
- invokeType = data["invokeType"].atom;
+ invokeType = data.at("invokeType").atom;
if (data.hasKey("eventName"))
- eventName = data["eventName"].atom;
+ eventName = data.at("eventName").atom;
if (data.hasKey("executableName"))
- executableName = data["executableName"].atom;
+ executableName = data.at("executableName").atom;
if (data.hasKey("executableXPath"))
- executableXPath = data["executableXPath"].atom;
+ executableXPath = data.at("executableXPath").atom;
if (data.hasKey("stateId"))
- stateId = data["stateId"].atom;
+ stateId = data.at("stateId").atom;
if (data.hasKey("transSourceId"))
- transSourceId = data["transSourceId"].atom;
+ transSourceId = data.at("transSourceId").atom;
if (data.hasKey("transTargetId"))
- transTargetId = data["transTargetId"].atom;
+ transTargetId = data.at("transTargetId").atom;
}
diff --git a/src/uscxml/debug/DebugSession.cpp b/src/uscxml/debug/DebugSession.cpp
index 46b414f..e785c84 100644
--- a/src/uscxml/debug/DebugSession.cpp
+++ b/src/uscxml/debug/DebugSession.cpp
@@ -106,9 +106,9 @@ Data DebugSession::debugPrepare(const Data& data) {
_isAttached = false;
if (data.hasKey("xml")) {
- _interpreter = Interpreter::fromXML(data["xml"].atom);
+ _interpreter = Interpreter::fromXML(data.at("xml").atom);
} else if (data.hasKey("url")) {
- _interpreter = Interpreter::fromURI(data["url"].atom);
+ _interpreter = Interpreter::fromURI(data.at("url").atom);
} else {
_interpreter = Interpreter();
}
@@ -119,7 +119,7 @@ Data DebugSession::debugPrepare(const Data& data) {
_debugger->attachSession(_interpreter, shared_from_this());
if (data.hasKey("url")) {
// this allows to resolve relative external reources
- _interpreter.setSourceURI(data["url"].atom);
+ _interpreter.setSourceURI(data.at("url").atom);
}
replyData.compound["status"] = Data("success", Data::VERBATIM);
} else {
@@ -139,7 +139,7 @@ Data DebugSession::debugAttach(const Data& data) {
return replyData;
}
- std::string interpreterId = data["attach"].atom;
+ std::string interpreterId = data.at("attach").atom;
bool interpreterFound = false;
// find interpreter for sessionid
@@ -354,7 +354,7 @@ Data DebugSession::debugEval(const Data& data) {
return replyData;
}
- std::string expr = data["expression"].atom;
+ std::string expr = data.at("expression").atom;
if (!_interpreter) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
diff --git a/src/uscxml/debug/DebuggerServlet.cpp b/src/uscxml/debug/DebuggerServlet.cpp
index 12783b4..a570263 100644
--- a/src/uscxml/debug/DebuggerServlet.cpp
+++ b/src/uscxml/debug/DebuggerServlet.cpp
@@ -65,22 +65,22 @@ void DebuggerServlet::returnData(const HTTPServer::Request& request, Data replyD
}
bool DebuggerServlet::isCORS(const HTTPServer::Request& request) {
- return (request.data["type"].atom == "options" &&
- request.data["header"].hasKey("Origin") &&
- request.data["header"].hasKey("Access-Control-Request-Method"));
+ return (request.data.at("type").atom == "options" &&
+ request.data.at("header").hasKey("Origin") &&
+ request.data.at("header").hasKey("Access-Control-Request-Method"));
}
void DebuggerServlet::handleCORS(const HTTPServer::Request& request) {
HTTPServer::Reply corsReply(request);
- if (request.data["header"].hasKey("Origin")) {
- corsReply.headers["Access-Control-Allow-Origin"] = request.data["header"]["Origin"].atom;
+ if (request.data.at("header").hasKey("Origin")) {
+ corsReply.headers["Access-Control-Allow-Origin"] = request.data.at("header").at("Origin").atom;
} else {
corsReply.headers["Access-Control-Allow-Origin"] = "*";
}
- if (request.data["header"].hasKey("Access-Control-Request-Method"))
- corsReply.headers["Access-Control-Allow-Methods"] = request.data["header"]["Access-Control-Request-Method"].atom;
- if (request.data["header"].hasKey("Access-Control-Request-Headers"))
- corsReply.headers["Access-Control-Allow-Headers"] = request.data["header"]["Access-Control-Request-Headers"].atom;
+ if (request.data.at("header").hasKey("Access-Control-Request-Method"))
+ corsReply.headers["Access-Control-Allow-Methods"] = request.data.at("header").at("Access-Control-Request-Method").atom;
+ if (request.data.at("header").hasKey("Access-Control-Request-Headers"))
+ corsReply.headers["Access-Control-Allow-Headers"] = request.data.at("header").at("Access-Control-Request-Headers").atom;
// std::cout << "CORS!" << std::endl << request << std::endl;
HTTPServer::reply(corsReply);
@@ -100,20 +100,20 @@ bool DebuggerServlet::httpRecvRequest(const HTTPServer::Request& request) {
Data replyData;
// process request that don't need a session
if (false) {
- } else if (boost::starts_with(request.data["path"].atom, "/debug/connect")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/connect")) {
processConnect(request);
return true;
- } else if (boost::starts_with(request.data["path"].atom, "/debug/sessions")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/sessions")) {
processListSessions(request);
return true;
}
// get session or return error
if (false) {
- } else if (!request.data["content"].hasKey("session")) {
+ } else if (!request.data.at("content").hasKey("session")) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
replyData.compound["reason"] = Data("No session given", Data::VERBATIM);
- } else if (_sessionForId.find(request.data["content"]["session"].atom) == _sessionForId.end()) {
+ } else if (_sessionForId.find(request.data.at("content").at("session").atom) == _sessionForId.end()) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
replyData.compound["reason"] = Data("No such session", Data::VERBATIM);
}
@@ -122,46 +122,46 @@ bool DebuggerServlet::httpRecvRequest(const HTTPServer::Request& request) {
return true;
}
- boost::shared_ptr<DebugSession> session = _sessionForId[request.data["content"]["session"].atom];
+ boost::shared_ptr<DebugSession> session = _sessionForId[request.data.at("content").at("session").atom];
if (false) {
- } else if (boost::starts_with(request.data["path"].atom, "/debug/poll")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/poll")) {
// save long-standing client poll
_clientConns[session] = request;
serverPushData(session);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/disconnect")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/disconnect")) {
processDisconnect(request);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/enable/all")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/enable/all")) {
replyData = session->enableAllBreakPoints();
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/disable/all")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/disable/all")) {
replyData = session->disableAllBreakPoints();
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/skipto")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/skipto")) {
replyData = session->skipToBreakPoint(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/add")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/add")) {
replyData = session->addBreakPoint(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/remove")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/remove")) {
replyData = session->removeBreakPoint(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/enable")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/enable")) {
replyData = session->enableBreakPoint(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/breakpoint/disable")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/breakpoint/disable")) {
replyData = session->disableBreakPoint(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/stop")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/stop")) {
replyData = session->debugStop(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/prepare")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/prepare")) {
replyData = session->debugPrepare(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/attach")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/attach")) {
replyData = session->debugAttach(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/start")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/start")) {
replyData = session->debugStart(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/step")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/step")) {
replyData = session->debugStep(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/pause")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/pause")) {
replyData = session->debugPause(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/resume")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/resume")) {
replyData = session->debugResume(request.data["content"]);
- } else if (boost::starts_with(request.data["path"].atom, "/debug/eval")) {
+ } else if (boost::starts_with(request.data.at("path").atom, "/debug/eval")) {
replyData = session->debugEval(request.data["content"]);
}
@@ -192,13 +192,13 @@ void DebuggerServlet::processDisconnect(const HTTPServer::Request& request) {
Data replyData;
- if (!request.data["content"].hasKey("session")) {
+ if (!request.data.at("content").hasKey("session")) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
replyData.compound["reason"] = Data("No session given", Data::VERBATIM);
returnData(request, replyData);
}
- std::string sessionId = request.data["content"]["session"].atom;
+ std::string sessionId = request.data.at("content").at("session").atom;
if (_sessionForId.find(sessionId) == _sessionForId.end()) {
replyData.compound["status"] = Data("failure", Data::VERBATIM);
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
index 593aadc..a7d7755 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
@@ -128,6 +128,9 @@ bool PromelaDataModel::evalAsBool(const Arabica::DOM::Node<std::string>& node, c
}
std::string PromelaDataModel::evalAsString(const std::string& expr) {
+ if (isDeclared(expr)) {
+ return Data::toJSON(_variables[expr]);
+ }
return expr;
}
@@ -135,12 +138,12 @@ void PromelaDataModel::assign(const Element<std::string>& assignElem,
const Node<std::string>& node,
const std::string& content) {
PromelaParser parser(content, PromelaParser::PROMELA_DECL);
- declare(parser.ast);
+ evaluateDecl(parser.ast);
// parser.dump();
// std::cout << Data::toJSON(_variables) << std::endl;
}
-void PromelaDataModel::declare(void* ast) {
+void PromelaDataModel::evaluateDecl(void* ast) {
PromelaParserNode* node = (PromelaParserNode*)ast;
if (false) {
} else if (node->type == DECL) {
@@ -194,7 +197,7 @@ void PromelaDataModel::declare(void* ast) {
_variables.compound[name->value] = variable;
} else {
- assert(false);
+ throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
}
}
assert(opIter == node->operands.end());
@@ -202,8 +205,10 @@ void PromelaDataModel::declare(void* ast) {
for (std::list<PromelaParserNode*>::iterator declIter = node->operands.begin();
declIter != node->operands.end();
declIter++) {
- declare(*declIter);
+ evaluateDecl(*declIter);
}
+ } else {
+ throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
}
}
@@ -214,6 +219,7 @@ int PromelaDataModel::evaluateExpr(void* ast) {
case CONST:
return strTo<int>(node->value);
case NAME:
+ case VAR_ARRAY:
return getVariable(node);
case PLUS:
return evaluateExpr(*opIter++) + evaluateExpr(*opIter++);
@@ -239,9 +245,14 @@ int PromelaDataModel::evaluateExpr(void* ast) {
return evaluateExpr(*opIter++) << evaluateExpr(*opIter++);
case RSHIFT:
return evaluateExpr(*opIter++) >> evaluateExpr(*opIter++);
+ case AND:
+ return evaluateExpr(*opIter++) != 0 && evaluateExpr(*opIter++) != 0;
+ case OR:
+ return evaluateExpr(*opIter++) != 0 || evaluateExpr(*opIter++) != 0;
default:
- assert(false);
+ throwErrorExecution("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
}
+ return 0;
}
void PromelaDataModel::evaluateStmnt(void* ast) {
@@ -261,26 +272,79 @@ void PromelaDataModel::evaluateStmnt(void* ast) {
break;
}
default:
- assert(false);
+ throwErrorExecution("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
}
}
void PromelaDataModel::setVariable(void* ast, int value) {
PromelaParserNode* node = (PromelaParserNode*)ast;
- _variables.compound[node->value].compound["value"] = Data(value, Data::VERBATIM);
+
+ std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
+ switch (node->type) {
+ case VAR_ARRAY: {
+ PromelaParserNode* name = *opIter++;
+ PromelaParserNode* expr = *opIter++;
+ int index = evaluateExpr(expr);
+
+ if (_variables.compound.find(name->value) == _variables.compound.end()) {
+ throwErrorExecution("No variable " + name->value + " was declared");
+ }
+
+ if (!_variables[name->value].hasKey("size")) {
+ throwErrorExecution("Variable " + name->value + " is no array");
+ }
+
+ if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
+ throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ }
+
+ _variables.compound[name->value].compound["value"][index] = Data(value, Data::VERBATIM);
+
+ break;
+ }
+ case NAME:
+ _variables.compound[node->value].compound["value"] = Data(value, Data::VERBATIM);
+ break;
+ default:
+ break;
+ }
+
+// std::cout << Data::toJSON(_variables) << std::endl;
}
int PromelaDataModel::getVariable(void* ast) {
PromelaParserNode* node = (PromelaParserNode*)ast;
+// node->dump();
- if (_variables.compound.find(node->value) == _variables.compound.end()) {
- uscxml::Event exc;
- exc.data.compound["exception"] = uscxml::Data("No variable " + node->value + " was declared", uscxml::Data::VERBATIM);
- exc.name = "error.execution";
- exc.eventType = uscxml::Event::PLATFORM;
- throw exc;
+ std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
+ switch(node->type) {
+ case NAME:
+ if (_variables.compound.find(node->value) == _variables.compound.end()) {
+ throwErrorExecution("No variable " + node->value + " was declared");
+ }
+ return strTo<int>(_variables[node->value]["value"]);
+ case VAR_ARRAY: {
+ PromelaParserNode* name = *opIter++;
+ PromelaParserNode* expr = *opIter++;
+ int index = evaluateExpr(expr);
+
+ if (_variables.compound.find(name->value) == _variables.compound.end()) {
+ throwErrorExecution("No variable " + name->value + " was declared");
+ }
+
+ if (!_variables[name->value].hasKey("size")) {
+ throwErrorExecution("Variable " + name->value + " is no array");
+ }
+
+ if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
+ throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ }
+ return _variables.compound[name->value].compound["value"][index];
+ }
+ default:
+ throwErrorExecution("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
}
- return strTo<int>(_variables[node->value]["value"]);
+ return 0;
}
void PromelaDataModel::assign(const std::string& location, const Data& data) {
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
index aaafa9b..e6a7894 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h
@@ -82,7 +82,7 @@ public:
protected:
- void declare(void* ast);
+ void evaluateDecl(void* ast);
int evaluateExpr(void* ast);
void evaluateStmnt(void* ast);
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
index ba89e14..a27d2df 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
@@ -9,37 +9,44 @@ int promela_lex_init (void**); \
int promela_lex_destroy (void*); \
void promela_error (uscxml::PromelaParser* ctx, void* yyscanner, const char* err) {
- uscxml::Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = uscxml::Data(err, uscxml::Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = uscxml::Event::PLATFORM;
- throw exceptionEvent;
+ uscxml::Event excEvent;
+ excEvent.data.compound["exception"] = uscxml::Data(err, uscxml::Data::VERBATIM);
+ excEvent.name = "error.execution";
+ excEvent.eventType = uscxml::Event::PLATFORM;
+ throw excEvent;
}
namespace uscxml {
+PromelaParser::PromelaParser(const std::string& expr) {
+ init(expr);
+}
+
PromelaParser::PromelaParser(const std::string& expr, Type expectedType) {
+ init(expr);
+ if (type != expectedType) {
+ std::stringstream ss;
+ ss << "Promela syntax type mismatch: Expected " << typeToDesc(expectedType) << " but got " << typeToDesc(type);
+
+ uscxml::Event excEvent;
+ excEvent.data.compound["exception"] = uscxml::Data(ss.str(), uscxml::Data::VERBATIM);
+ excEvent.name = "error.execution";
+ excEvent.eventType = uscxml::Event::PLATFORM;
+ throw excEvent;
+ }
+}
+
+void PromelaParser::init(const std::string& expr) {
input_length = expr.length() + 5; // plus some zero terminators
input = (char*) calloc(1, input_length);
memcpy(input, expr.c_str(), expr.length());
-
+
promela_lex_init(&scanner);
// promela_assign_set_extra(ast, &scanner);
promela__scan_buffer(input, input_length, scanner);
promela_parse(this, scanner);
-
- if (type != expectedType) {
- std::stringstream ss;
- ss << "Promela syntax type mismatch: Expected " << typeToDesc(expectedType) << " but got " << typeToDesc(type);
-
- uscxml::Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = uscxml::Data(ss.str(), uscxml::Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = uscxml::Event::PLATFORM;
- throw exceptionEvent;
- }
}
-
+
PromelaParser::~PromelaParser() {
free(input);
promela_lex_destroy(scanner);
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.h b/src/uscxml/plugins/datamodel/promela/PromelaParser.h
index 6daa154..0cca365 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaParser.h
+++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.h
@@ -64,6 +64,7 @@ public:
static std::string typeToDesc(int type);
+ PromelaParser(const std::string& expr);
PromelaParser(const std::string& expr, Type expectedType);
virtual ~PromelaParser();
@@ -104,7 +105,9 @@ public:
Type type;
protected:
-
+
+ void init(const std::string& expr);
+
void* scanner;
char* input;
size_t input_length;
diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp
index 10bef82..5cdcec1 100644
--- a/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp
+++ b/src/uscxml/plugins/datamodel/promela/parser/promela.tab.cpp
@@ -1671,13 +1671,13 @@ yyreduce:
case 6:
/* Line 1787 of yacc.c */
#line 101 "promela.ypp"
- { (yyval.node) = ctx->value(NAME, yylval.value); }
+ { (yyval.node) = ctx->value(NAME, (yyvsp[(1) - (1)].value)); }
break;
case 7:
/* Line 1787 of yacc.c */
#line 102 "promela.ypp"
- {}
+ { (yyval.node) = ctx->node(VAR_ARRAY, 2, ctx->value(NAME, (yyvsp[(1) - (4)].value)), (yyvsp[(3) - (4)].node)); }
break;
case 8:
diff --git a/src/uscxml/plugins/datamodel/promela/parser/promela.ypp b/src/uscxml/plugins/datamodel/promela/parser/promela.ypp
index 6147d40..b33ebd1 100644
--- a/src/uscxml/plugins/datamodel/promela/parser/promela.ypp
+++ b/src/uscxml/plugins/datamodel/promela/parser/promela.ypp
@@ -98,8 +98,8 @@ program :
varref : cmpnd {}
;
-pfld : NAME { $$ = ctx->value(NAME, yylval.value); }
- | NAME '[' expr ']' {}
+pfld : NAME { $$ = ctx->value(NAME, $1); }
+ | NAME '[' expr ']' { $$ = ctx->node(VAR_ARRAY, 2, ctx->value(NAME, $1), $3); }
;
cmpnd : pfld {}
diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
index d4355b5..e607cf4 100644
--- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
@@ -65,8 +65,8 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
// these are the XHR requests
- if (iequals(req.data["header"]["X-Requested-With"].atom, "XMLHttpRequest")) {
- if (iequals(req.data["type"].atom, "get")) {
+ if (iequals(req.data.at("header").at("X-Requested-With").atom, "XMLHttpRequest")) {
+ if (iequals(req.data.at("type").atom, "get")) {
// the long-polling GET
if (_longPoll) {
evhttp_send_error(_longPoll.evhttpReq, 204, NULL);
@@ -84,10 +84,10 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
if (ev.data["header"]["X-SCXML-Name"]) {
ev.name = ev.data["header"]["X-SCXML-Name"].atom;
} else {
- ev.name = req.data["type"].atom;
+ ev.name = req.data.at("type").atom;
}
ev.origin = _invokeId;
- ev.initContent(req.data["content"].atom);
+ ev.initContent(req.data.at("content").atom);
ev.data.compound["Connection"] = req.data;
// content is already on ev.raw
ev.data.compound["Connection"].compound.erase("content");
@@ -102,7 +102,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
// initial request for a document
if (!req.data["query"] && // no query parameters
- iequals(req.data["type"].atom, "get") && // request type is GET
+ iequals(req.data.at("type").atom, "get") && // request type is GET
req.content.length() == 0) { // no content
HTTPServer::Reply reply(req);
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 085d919..9c1ba45 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -122,11 +122,11 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) {
*/
// this will call the const subscript operator
- if (req.data["content"]["_scxmleventname"]) {
- reqEvent.name = req.data["content"]["_scxmleventname"].atom;
+ if (req.data.at("content").hasKey("_scxmleventname")) {
+ reqEvent.name = req.data.at("content").at("_scxmleventname").atom;
}
- if (req.data["content"]["content"]) {
- reqEvent.content = req.data["content"]["content"].atom;
+ if (req.data.at("content").hasKey("content")) {
+ reqEvent.content = req.data.at("content").at("content").atom;
}
// check whether we can parse it as XML
diff --git a/test/samples/uscxml/promela/test-simple-promela.scxml b/test/samples/uscxml/promela/test-simple-promela.scxml
index d209ca6..00b95e4 100644
--- a/test/samples/uscxml/promela/test-simple-promela.scxml
+++ b/test/samples/uscxml/promela/test-simple-promela.scxml
@@ -31,10 +31,14 @@
<state id="init">
<onentry>
<script>
+ busy[4 - 3] = 1;
+ </script>
+ <log expr="busy" />
+ <script>
v2=1; v3=1;
</script>
</onentry>
- <transition target="pass" cond="v2==v3">
+ <transition target="pass" cond="v2==v3 &amp;&amp; busy[1] == 1">
</transition>
<transition target="fail" />
</state>
diff --git a/test/src/test-promela-parser.cpp b/test/src/test-promela-parser.cpp
index 6dc58d1..940e55a 100644
--- a/test/src/test-promela-parser.cpp
+++ b/test/src/test-promela-parser.cpp
@@ -39,6 +39,7 @@ int main(int argc, char** argv) {
// expressions.push_back("(a + 1) << b");
// expressions.push_back("(b < N)");
// expressions.push_back("(mt+1)%MAX;");
+// expressions.push_back("state[0] = state[3] + 5 * state[3*2/n]");
/* statements */
// expressions.push_back("t = Bturn;");