From 71c334bf4e35559496feac3f3cf00b72ceb88812 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Fri, 11 Apr 2014 09:58:48 +0200 Subject: More work on promela DM changed const of Data subscript operator and introduced at(key) and item(index) --- src/uscxml/Factory.cpp | 17 ++++ src/uscxml/Factory.h | 3 + src/uscxml/Message.h | 37 +++++++-- src/uscxml/debug/Breakpoint.cpp | 46 +++++------ src/uscxml/debug/DebugSession.cpp | 10 +-- src/uscxml/debug/DebuggerServlet.cpp | 66 ++++++++-------- .../plugins/datamodel/promela/PromelaDataModel.cpp | 92 ++++++++++++++++++---- .../plugins/datamodel/promela/PromelaDataModel.h | 2 +- .../plugins/datamodel/promela/PromelaParser.cpp | 43 +++++----- .../plugins/datamodel/promela/PromelaParser.h | 5 +- .../datamodel/promela/parser/promela.tab.cpp | 4 +- .../plugins/datamodel/promela/parser/promela.ypp | 4 +- src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp | 10 +-- .../ioprocessor/basichttp/BasicHTTPIOProcessor.cpp | 8 +- .../uscxml/promela/test-simple-promela.scxml | 6 +- test/src/test-promela-parser.cpp | 1 + 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) { 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::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::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 session = _sessionForId[request.data["content"]["session"].atom]; + boost::shared_ptr 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& 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& assignElem, const Node& 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::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(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::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(_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::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(_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(_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(_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 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 @@ + + - + 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;"); -- cgit v0.12