summaryrefslogtreecommitdiffstats
path: root/src/uscxml/Interpreter.cpp
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-08-22 16:21:18 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-08-22 16:21:18 (GMT)
commit9509b795c7493d7b351dc25855a6a82cd392deb1 (patch)
tree11f1950bab743ecbe2ac8d75177702a3620ef15c /src/uscxml/Interpreter.cpp
parentd6fa07c2b4b3eb0c8db4f79927f88de72892dcc2 (diff)
downloaduscxml-9509b795c7493d7b351dc25855a6a82cd392deb1.zip
uscxml-9509b795c7493d7b351dc25855a6a82cd392deb1.tar.gz
uscxml-9509b795c7493d7b351dc25855a6a82cd392deb1.tar.bz2
Moved InterpreterIssues to own source file
Diffstat (limited to 'src/uscxml/Interpreter.cpp')
-rw-r--r--src/uscxml/Interpreter.cpp519
1 files changed, 11 insertions, 508 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 370bef0..b9e7145 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -713,513 +713,8 @@ void InterpreterImpl::reset() {
setInterpreterState(USCXML_INSTANTIATED);
}
-InterpreterIssue::InterpreterIssue(const std::string& msg, Arabica::DOM::Node<std::string> node, IssueSeverity severity) : message(msg), node(node), severity(severity) {
- if (node)
- xPath = DOMUtils::xPathForNode(node);
-}
-
std::list<InterpreterIssue> InterpreterImpl::validate() {
- // some things we need to prepare first
- if (_factory == NULL)
- _factory = Factory::getInstance();
- setupDOM();
-
- std::list<InterpreterIssue> issues;
-
- if (!_scxml) {
- InterpreterIssue issue("No SCXML element to be found", Node<std::string>(), InterpreterIssue::USCXML_ISSUE_FATAL);
- issues.push_back(issue);
- return issues;
- }
-
- _cachedStates.clear();
-
- NodeSet<std::string> scxmls = filterChildElements(_nsInfo.xmlNSPrefix + "scxml", _scxml, true);
- scxmls.push_back(_scxml);
-
- NodeSet<std::string> states = filterChildElements(_nsInfo.xmlNSPrefix + "state", _scxml, true);
- NodeSet<std::string> parallels = filterChildElements(_nsInfo.xmlNSPrefix + "parallel", _scxml, true);
- NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true);
- NodeSet<std::string> initials = filterChildElements(_nsInfo.xmlNSPrefix + "initial", _scxml, true);
- NodeSet<std::string> finals = filterChildElements(_nsInfo.xmlNSPrefix + "final", _scxml, true);
- NodeSet<std::string> onEntries = filterChildElements(_nsInfo.xmlNSPrefix + "onentry", _scxml, true);
- NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onexit", _scxml, true);
- NodeSet<std::string> histories = filterChildElements(_nsInfo.xmlNSPrefix + "history", _scxml, true);
-
- NodeSet<std::string> raises = filterChildElements(_nsInfo.xmlNSPrefix + "raise", _scxml, true);
- NodeSet<std::string> ifs = filterChildElements(_nsInfo.xmlNSPrefix + "if", _scxml, true);
- NodeSet<std::string> elseIfs = filterChildElements(_nsInfo.xmlNSPrefix + "elseif", _scxml, true);
- NodeSet<std::string> elses = filterChildElements(_nsInfo.xmlNSPrefix + "else", _scxml, true);
- NodeSet<std::string> foreachs = filterChildElements(_nsInfo.xmlNSPrefix + "foreach", _scxml, true);
- NodeSet<std::string> logs = filterChildElements(_nsInfo.xmlNSPrefix + "log", _scxml, true);
-
- NodeSet<std::string> dataModels = filterChildElements(_nsInfo.xmlNSPrefix + "datamodel", _scxml, true);
- NodeSet<std::string> datas = filterChildElements(_nsInfo.xmlNSPrefix + "data", _scxml, true);
- NodeSet<std::string> assigns = filterChildElements(_nsInfo.xmlNSPrefix + "assign", _scxml, true);
- NodeSet<std::string> doneDatas = filterChildElements(_nsInfo.xmlNSPrefix + "donedata", _scxml, true);
- NodeSet<std::string> contents = filterChildElements(_nsInfo.xmlNSPrefix + "content", _scxml, true);
- NodeSet<std::string> params = filterChildElements(_nsInfo.xmlNSPrefix + "param", _scxml, true);
- NodeSet<std::string> scripts = filterChildElements(_nsInfo.xmlNSPrefix + "script", _scxml, true);
-
- NodeSet<std::string> sends = filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true);
- NodeSet<std::string> cancels = filterChildElements(_nsInfo.xmlNSPrefix + "cancel", _scxml, true);
- NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true);
- NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", _scxml, true);
-
- NodeSet<std::string> allStates;
- allStates.push_back(states);
- allStates.push_back(parallels);
- allStates.push_back(histories);
- allStates.push_back(finals);
-
- NodeSet<std::string> allExecContents;
- allExecContents.push_back(raises);
- allExecContents.push_back(ifs);
- allExecContents.push_back(elseIfs);
- allExecContents.push_back(elses);
- allExecContents.push_back(foreachs);
- allExecContents.push_back(logs);
- allExecContents.push_back(sends);
- allExecContents.push_back(assigns);
- allExecContents.push_back(scripts);
- allExecContents.push_back(cancels);
-
- NodeSet<std::string> allElements;
- allElements.push_back(allStates);
- allElements.push_back(allExecContents);
- allElements.push_back(transitions);
- allElements.push_back(initials);
- allElements.push_back(onEntries);
- allElements.push_back(onExits);
- allElements.push_back(dataModels);
- allElements.push_back(datas);
- allElements.push_back(doneDatas);
- allElements.push_back(contents);
- allElements.push_back(params);
- allElements.push_back(invokes);
- allElements.push_back(finalizes);
-
-
- std::set<std::string> execContentSet;
- execContentSet.insert("raise");
- execContentSet.insert("if");
- execContentSet.insert("elseif");
- execContentSet.insert("else");
- execContentSet.insert("foreach");
- execContentSet.insert("log");
- execContentSet.insert("send");
- execContentSet.insert("assign");
- execContentSet.insert("script");
- execContentSet.insert("cancel");
-
- std::map<std::string, std::set<std::string> > validChildren;
- validChildren["scxml"].insert("state");
- validChildren["scxml"].insert("parallel");
- validChildren["scxml"].insert("final");
- validChildren["scxml"].insert("datamodel");
- validChildren["scxml"].insert("script");
-
- validChildren["state"].insert("onentry");
- validChildren["state"].insert("onexit");
- validChildren["state"].insert("transition");
- validChildren["state"].insert("initial");
- validChildren["state"].insert("state");
- validChildren["state"].insert("parallel");
- validChildren["state"].insert("final");
- validChildren["state"].insert("history");
- validChildren["state"].insert("datamodel");
- validChildren["state"].insert("invoke");
-
- validChildren["parallel"].insert("onentry");
- validChildren["parallel"].insert("onexit");
- validChildren["parallel"].insert("transition");
- validChildren["parallel"].insert("state");
- validChildren["parallel"].insert("parallel");
- validChildren["parallel"].insert("history");
- validChildren["parallel"].insert("datamodel");
- validChildren["parallel"].insert("invoke");
-
- validChildren["transition"] = execContentSet;
- validChildren["onentry"] = execContentSet;
- validChildren["onexit"] = execContentSet;
- validChildren["finalize"] = execContentSet;
-
- validChildren["if"] = execContentSet;
- validChildren["elseif"] = execContentSet;
- validChildren["else"] = execContentSet;
- validChildren["foreach"] = execContentSet;
-
- validChildren["initial"].insert("transition");
- validChildren["history"].insert("transition");
-
- validChildren["final"].insert("onentry");
- validChildren["final"].insert("onexit");
- validChildren["final"].insert("donedata");
-
- validChildren["datamodel"].insert("data");
-
- validChildren["donedata"].insert("content");
- validChildren["donedata"].insert("param");
-
- validChildren["send"].insert("content");
- validChildren["send"].insert("param");
-
- validChildren["invoke"].insert("content");
- validChildren["invoke"].insert("param");
- validChildren["invoke"].insert("finalize");
-
- std::map<std::string, std::set<std::string> > validParents;
- for (std::map<std::string, std::set<std::string> >::iterator parentIter = validChildren.begin(); parentIter != validChildren.end(); parentIter++) {
- for (std::set<std::string>::iterator childIter = parentIter->second.begin(); childIter != parentIter->second.end(); childIter++) {
- validParents[*childIter].insert(parentIter->first);
- }
- }
-
- for (int i = 0; i < allStates.size(); i++) {
- Element<std::string> state = Element<std::string>(allStates[i]);
-
- if (isMember(state, finals) && !HAS_ATTR(state, "id")) // id is not required for finals
- continue;
-
- // check for existance of id attribute
- if (!HAS_ATTR(state, "id")) {
- issues.push_back(InterpreterIssue("State has no 'id' attribute", state, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- std::string stateId = ATTR(state, "id");
-
- // check for uniqueness of id attribute
- if (_cachedStates.find(stateId) != _cachedStates.end()) {
- issues.push_back(InterpreterIssue("Duplicate state with id '" + stateId + "'", state, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- _cachedStates[ATTR(state, "id")] = state;
- }
-
- for (int i = 0; i < transitions.size(); i++) {
- Element<std::string> transition = Element<std::string>(transitions[i]);
-
- // check for valid target
- std::list<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target"));
- for (std::list<std::string>::iterator targetIter = targetIds.begin(); targetIter != targetIds.end(); targetIter++) {
- if (_cachedStates.find(*targetIter) == _cachedStates.end()) {
- issues.push_back(InterpreterIssue("Transition has non-existant target state with id '" + *targetIter + "'", transition, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- }
- }
-
- // check for redundancy of transition
- for (int i = 0; i < allStates.size(); i++) {
- Element<std::string> state = Element<std::string>(allStates[i]);
- NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", state, false);
-
- transitions.to_document_order();
-
- for (int j = 1; j < transitions.size(); j++) {
- Element<std::string> transition = Element<std::string>(transitions[j]);
- for (int k = 0; k < j; k++) {
- Element<std::string> earlierTransition = Element<std::string>(transitions[k]);
-
- // will the earlier transition always be enabled when the later is?
- if (!HAS_ATTR(earlierTransition, "cond")) {
- // earlier transition has no condition -> check event descriptor
- if (!HAS_ATTR(earlierTransition, "event")) {
- // earlier transition is eventless
- issues.push_back(InterpreterIssue("Transition can never be optimally enabled", transition, InterpreterIssue::USCXML_ISSUE_INFO));
- goto NEXT_TRANSITION;
-
- } else if (HAS_ATTR(transition, "event")) {
- // does the earlier transition match all our events?
- std::list<std::string> events = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "event"));
-
- bool allMatched = true;
- for (std::list<std::string>::iterator eventIter = events.begin(); eventIter != events.end(); eventIter++) {
- if (!nameMatch(ATTR(earlierTransition, "event"), *eventIter)) {
- allMatched = false;
- break;
- }
- }
-
- if (allMatched) {
- issues.push_back(InterpreterIssue("Transition can never be optimally enabled", transition, InterpreterIssue::USCXML_ISSUE_INFO));
- goto NEXT_TRANSITION;
- }
- }
- }
- }
- NEXT_TRANSITION:;
- }
- }
-
- // check for valid initial attribute
- {
- NodeSet<std::string> withInitialAttr;
- withInitialAttr.push_back(allStates);
- withInitialAttr.push_back(_scxml);
-
- for (int i = 0; i < withInitialAttr.size(); i++) {
- Element<std::string> state = Element<std::string>(withInitialAttr[i]);
- if (HAS_ATTR(state, "initial")) {
- std::list<std::string> intials = InterpreterImpl::tokenizeIdRefs(ATTR(state, "initial"));
- for (std::list<std::string>::iterator initIter = intials.begin(); initIter != intials.end(); initIter++) {
- if (_cachedStates.find(*initIter) == _cachedStates.end()) {
- issues.push_back(InterpreterIssue("Initial attribute has invalid target state with id '" + *initIter + "'", state, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- }
- }
- }
- }
-
- // check that all invokers exists
- {
- for (int i = 0; i < invokes.size(); i++) {
- Element<std::string> invoke = Element<std::string>(invokes[i]);
- if (HAS_ATTR(invoke, "type") && !_factory->hasInvoker(ATTR(invoke, "type"))) {
- issues.push_back(InterpreterIssue("Invoke with unknown type '" + ATTR(invoke, "type") + "'", invoke, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- }
- }
-
- // check that all io processors exists
- {
- for (int i = 0; i < sends.size(); i++) {
- Element<std::string> send = Element<std::string>(sends[i]);
- if (HAS_ATTR(send, "type") && !_factory->hasIOProcessor(ATTR(send, "type"))) {
- issues.push_back(InterpreterIssue("Send to unknown IO Processor '" + ATTR(send, "type") + "'", send, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- }
- }
-
- // check that all custom executable content is known
- {
- NodeSet<std::string> allExecContentContainers;
- allExecContentContainers.push_back(onEntries);
- allExecContentContainers.push_back(onExits);
- allExecContentContainers.push_back(transitions);
- allExecContentContainers.push_back(finalizes);
-
- for (int i = 0; i < allExecContentContainers.size(); i++) {
- Element<std::string> block = Element<std::string>(allExecContentContainers[i]);
- NodeSet<std::string> execContents = filterChildType(Node_base::ELEMENT_NODE, block);
- for (int j = 0; j < execContents.size(); j++) {
- Element<std::string> execContent = Element<std::string>(execContents[j]);
- // SCXML specific executable content, always available
- if (isMember(execContent, allExecContents)) {
- continue;
- }
- if (!_factory->hasExecutableContent(execContent.getLocalName(), execContent.getNamespaceURI())) {
- issues.push_back(InterpreterIssue("Executable content element '" + execContent.getLocalName() + "' in namespace '" + execContent.getNamespaceURI() + "' unknown", execContent, InterpreterIssue::USCXML_ISSUE_FATAL));
- continue;
- }
- }
- }
- }
-
- // check that all SCXML elements have valid parents
- {
- for (int i = 0; i < allElements.size(); i++) {
- Element<std::string> element = Element<std::string>(allElements[i]);
- std::string localName = LOCALNAME(element);
- if (!element.getParentNode() || element.getParentNode().getNodeType() != Node_base::ELEMENT_NODE) {
- issues.push_back(InterpreterIssue("Parent of " + localName + " is no element", element, InterpreterIssue::USCXML_ISSUE_INFO));
- continue;
- }
-
- Element<std::string> parent = Element<std::string>(element.getParentNode());
- std::string parentName = LOCALNAME(parent);
-
- if (validParents[localName].find(parentName) == validParents[localName].end()) {
- issues.push_back(InterpreterIssue("Element " + parentName + " can be no parent of " + localName, element, InterpreterIssue::USCXML_ISSUE_INFO));
- continue;
- }
- }
- }
-
-
- // check that the datamodel is known
- if (HAS_ATTR(_scxml, "datamodel")) {
- if (!_factory->hasDataModel(ATTR(_scxml, "datamodel"))) {
- issues.push_back(InterpreterIssue("SCXML document requires unknown datamodel '" + ATTR(_scxml, "datamodel") + "'", _scxml, InterpreterIssue::USCXML_ISSUE_FATAL));
-
- // we cannot even check the rest as we require a datamodel
- return issues;
- }
- }
-
- bool instantiatedDataModel = false;
- // instantiate datamodel if not explicitly set
- if (!_dataModel) {
- if (HAS_ATTR(_scxml, "datamodel")) {
- // might throw
- _dataModel = _factory->createDataModel(ATTR(_scxml, "datamodel"), this);
- instantiatedDataModel = true;
- } else {
- _dataModel = _factory->createDataModel("null", this);
- }
- }
-
-
- // test all scripts for valid syntax
- {
- for (int i = 0; i < scripts.size(); i++) {
- Element<std::string> script = Element<std::string>(scripts[i]);
-
- if (script.hasChildNodes()) {
- // search for the text node with the actual script
- std::string scriptContent;
- for (Node<std::string> child = script.getFirstChild(); child; child = child.getNextSibling()) {
- if (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE)
- scriptContent += child.getNodeValue();
- }
-
- if (!_dataModel.isValidSyntax(scriptContent)) {
- issues.push_back(InterpreterIssue("Syntax error in script", script, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- }
- }
-
- // test the various attributes with datamodel expressions for valid syntax
- {
- NodeSet<std::string> withCondAttrs;
- withCondAttrs.push_back(transitions);
- withCondAttrs.push_back(ifs);
- withCondAttrs.push_back(elseIfs);
-
- for (int i = 0; i < withCondAttrs.size(); i++) {
- Element<std::string> condAttr = Element<std::string>(withCondAttrs[i]);
- if (HAS_ATTR(condAttr, "cond")) {
- if (!_dataModel.isValidSyntax(ATTR(condAttr, "cond"))) {
- issues.push_back(InterpreterIssue("Syntax error in cond attribute", condAttr, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- }
- }
-
- {
- NodeSet<std::string> withExprAttrs;
- withExprAttrs.push_back(logs);
- withExprAttrs.push_back(datas);
- withExprAttrs.push_back(assigns);
- withExprAttrs.push_back(contents);
- withExprAttrs.push_back(params);
-
- for (int i = 0; i < withExprAttrs.size(); i++) {
- Element<std::string> withExprAttr = Element<std::string>(withExprAttrs[i]);
- if (HAS_ATTR(withExprAttr, "expr")) {
- if (isMember(withExprAttr, datas) || isMember(withExprAttr, assigns)) {
- if (!_dataModel.isValidSyntax("foo = " + ATTR(withExprAttr, "expr"))) { // TODO: this is ECMAScripty!
- issues.push_back(InterpreterIssue("Syntax error in expr attribute", withExprAttr, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- } else {
- if (!_dataModel.isValidSyntax(ATTR(withExprAttr, "expr"))) {
- issues.push_back(InterpreterIssue("Syntax error in expr attribute", withExprAttr, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- }
- }
- }
-
- {
- for (int i = 0; i < foreachs.size(); i++) {
- Element<std::string> foreach = Element<std::string>(foreachs[i]);
- if (HAS_ATTR(foreach, "array")) {
- if (!_dataModel.isValidSyntax(ATTR(foreach, "array"))) {
- issues.push_back(InterpreterIssue("Syntax error in array attribute", foreach, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(foreach, "item")) {
- if (!_dataModel.isValidSyntax(ATTR(foreach, "item"))) {
- issues.push_back(InterpreterIssue("Syntax error in item attribute", foreach, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(foreach, "index")) {
- if (!_dataModel.isValidSyntax(ATTR(foreach, "index"))) {
- issues.push_back(InterpreterIssue("Syntax error in index attribute", foreach, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- }
- }
-
- {
- for (int i = 0; i < sends.size(); i++) {
- Element<std::string> send = Element<std::string>(sends[i]);
- if (HAS_ATTR(send, "eventexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(send, "eventexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in eventexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(send, "targetexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(send, "targetexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in targetexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(send, "typeexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(send, "typeexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in typeexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(send, "idlocation")) {
- if (!_dataModel.isValidSyntax(ATTR(send, "idlocation"))) {
- issues.push_back(InterpreterIssue("Syntax error in idlocation attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- if (HAS_ATTR(send, "delayexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(send, "delayexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in delayexpr attribute", send, InterpreterIssue::USCXML_ISSUE_WARNING));
- }
- }
- }
-
- }
-
- {
- for (int i = 0; i < invokes.size(); i++) {
- Element<std::string> invoke = Element<std::string>(invokes[i]);
- if (HAS_ATTR(invoke, "typeexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(invoke, "typeexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in typeexpr attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- if (HAS_ATTR(invoke, "srcexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(invoke, "srcexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in srcexpr attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- if (HAS_ATTR(invoke, "idlocation")) {
- if (!_dataModel.isValidSyntax(ATTR(invoke, "idlocation"))) {
- issues.push_back(InterpreterIssue("Syntax error in idlocation attribute", invoke, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- }
- }
-
- {
- for (int i = 0; i < cancels.size(); i++) {
- Element<std::string> cancel = Element<std::string>(cancels[i]);
- if (HAS_ATTR(cancel, "sendidexpr")) {
- if (!_dataModel.isValidSyntax(ATTR(cancel, "sendidexpr"))) {
- issues.push_back(InterpreterIssue("Syntax error in sendidexpr attribute", cancel, InterpreterIssue::USCXML_ISSUE_WARNING));
- continue;
- }
- }
- }
- }
-
- if (instantiatedDataModel)
- _dataModel = DataModel();
-
- return issues;
+ return InterpreterIssue::forInterpreter(this);
}
std::ostream& operator<< (std::ostream& os, const InterpreterIssue& issue) {
@@ -2686,8 +2181,16 @@ Arabica::XPath::NodeSet<std::string> InterpreterImpl::getInitialStates(Arabica::
std::cout << "Getting initial state of " << TAGNAME(state) << " " << ATTR(state, "id") << std::endl;
#endif
+ if (isAtomic(state)) {
+ return Arabica::XPath::NodeSet<std::string>();
+ }
+
assert(isCompound(state) || isParallel(state));
+ if (isParallel(state)) {
+ return getChildStates(state);
+ }
+
// initial attribute at element
Arabica::DOM::Element<std::string> stateElem = (Arabica::DOM::Element<std::string>)state;
if (stateElem.hasAttribute("initial")) {
@@ -3003,8 +2506,8 @@ bool InterpreterImpl::isInitial(const Arabica::DOM::Element<std::string>& state)
if (isMember(state, getInitialStates(parent)))
return true; // every nested node
- if (isParallel(parent))
- return true;
+// if (isParallel(parent))
+// return true;
return false;
}