1 // Copyright (C) 2006-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #ifndef _LOOPPARSER_HXX_
21 #define _LOOPPARSER_HXX_
23 #include "parserBase.hxx"
28 #include "Exception.hxx"
29 #include "InlineNode.hxx"
30 #include "ServiceNode.hxx"
31 #include "ServiceInlineNode.hxx"
32 #include "OutputDataStreamPort.hxx"
33 #include "InputDataStreamPort.hxx"
34 #include "ForLoop.hxx"
35 #include "WhileLoop.hxx"
37 #include "ForEachLoop.hxx"
38 #include "OptimizerLoop.hxx"
47 template <class T=ENGINE::Loop*>
48 struct looptypeParser:parser
50 virtual void onStart(const XML_Char* el, const XML_Char** attr);
51 virtual void onEnd(const char *el,parser* child);
52 virtual void buildAttr(const XML_Char** attr);
54 virtual void name (const std::string& name);
55 virtual void state (const std::string& name);
56 virtual void property (const myprop& prop);
57 virtual void inline_ (ENGINE::InlineNode* const& n);
58 virtual void sinline (ENGINE::ServiceInlineNode* const& n);
59 virtual void service (ENGINE::ServiceNode* const& n);
60 virtual void server (ENGINE::ServerNode* const& n);
61 virtual void remote (ENGINE::InlineNode* const& n);
62 virtual void node (ENGINE::InlineNode* const& n);
63 virtual void forloop (ENGINE::ForLoop* const& b);
64 virtual void foreach (ENGINE::ForEachLoopGen* const& b);
65 virtual void optimizer (ENGINE::OptimizerLoop* const& b);
66 virtual void while_ (ENGINE::WhileLoop* const& b);
67 virtual void switch_ (ENGINE::Switch* const& b);
68 virtual void bloc (ENGINE::Bloc* const& b);
69 virtual void datalink (const mylink& l);
72 std::vector<T> _cnodes;
79 // A loop can contain forloop, whileloop or foreachloop
80 // We must respect the order : definition of loop, then while, for, .. and then onStart, onEnd for loop !!!
82 static std::string t3[]={"inline","sinline","service","server", "remote", "node","forloop","foreach","optimizer","while","switch","bloc",""};
85 void looptypeParser<T>::buildAttr(const XML_Char** attr)
89 this->required("name",attr);
90 for (int i = 0; attr[i]; i += 2)
92 if(std::string(attr[i]) == "name")name(attr[i+1]);
93 if(std::string(attr[i]) == "state")state(attr[i+1]);
97 void looptypeParser<T>::pre ()
103 void looptypeParser<T>::name (const std::string& name)
105 DEBTRACE( "bloc_name: " << name );
108 void looptypeParser<T>::state (const std::string& name)
110 DEBTRACE( "bloc_state: " << name );
114 void looptypeParser<T>::property (const myprop& prop)
116 DEBTRACE( "property_set" << prop._name << prop._value );
120 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
122 DEBTRACE( "loop_inline" << n->getName() );
123 _cnode->edSetNode(n);
124 std::string fullname=currentProc->names.back()+ n->getName();
125 currentProc->nodeMap[fullname]=n;
126 currentProc->inlineMap[fullname]=n;
129 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
131 DEBTRACE( "loop_sinline" << n->getName() )
132 _cnode->edSetNode(n);
133 std::string fullname=currentProc->names.back()+ n->getName();
134 currentProc->nodeMap[fullname]=n;
135 currentProc->serviceMap[fullname]=n;
138 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
140 DEBTRACE( "loop_service" << n->getName() )
141 _cnode->edSetNode(n);
142 std::string fullname=currentProc->names.back()+ n->getName();
143 currentProc->nodeMap[fullname]=n;
144 currentProc->serviceMap[fullname]=n;
147 void looptypeParser<T>::server (ENGINE::ServerNode* const& n)
149 DEBTRACE( "loop_server" << n->getName() )
150 _cnode->edSetNode(n);
151 std::string fullname=currentProc->names.back()+ n->getName();
152 currentProc->nodeMap[fullname]=n;
153 currentProc->inlineMap[fullname]=n;
157 void looptypeParser<T>::remote (YACS::ENGINE::InlineNode* const& n)
159 DEBTRACE( "loop_remote: " << n->getName() )
160 _cnode->edSetNode(n);
161 std::string fullname = currentProc->names.back()+n->getName();
162 currentProc->nodeMap[fullname]=n;
163 currentProc->inlineMap[fullname]=n;
167 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
169 DEBTRACE( "loop_node" << n->getName() )
170 _cnode->edSetNode(n);
171 std::string fullname=currentProc->names.back()+ n->getName();
172 currentProc->nodeMap[fullname]=n;
173 currentProc->inlineMap[fullname]=n;
176 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
178 DEBTRACE( "loop_forloop" << b->getName() )
179 _cnode->edSetNode(b);
180 std::string fullname=currentProc->names.back()+ b->getName();
181 currentProc->nodeMap[fullname]=b;
184 void looptypeParser<T>::foreach (ENGINE::ForEachLoopGen* const& b)
186 DEBTRACE("loop_foreach" << b->getName())
187 _cnode->edSetNode(b);
188 std::string fullname=currentProc->names.back()+ b->getName();
189 currentProc->nodeMap[fullname]=b;
190 fullname += ".splitter";
191 currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
194 void looptypeParser<T>::optimizer (ENGINE::OptimizerLoop* const& b)
196 DEBTRACE( "loop_optimizer: " << b->getName() );
197 _cnode->edSetNode(b);
198 std::string fullname = currentProc->names.back()+b->getName();
199 currentProc->nodeMap[fullname]=b;
200 //fullname += ".splitter";
201 //currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
204 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
206 DEBTRACE( "loop_while: " << b->getName() )
207 _cnode->edSetNode(b);
208 std::string fullname=currentProc->names.back()+ b->getName();
209 currentProc->nodeMap[fullname]=b;
212 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
214 DEBTRACE( "loop_switch: " << b->getName() )
215 _cnode->edSetNode(b);
216 std::string fullname=currentProc->names.back()+ b->getName();
217 currentProc->nodeMap[fullname]=b;
220 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
222 DEBTRACE( "loop_bloc " << b->getName() )
223 _cnode->edSetNode(b);
224 std::string fullname=currentProc->names.back()+ b->getName();
225 currentProc->nodeMap[fullname]=b;
229 void looptypeParser<T>::datalink (const mylink& l)
231 DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
234 //Try only relative name for from node
235 std::string fromname = currentProc->names.back()+l.fromnode();
236 if(currentProc->nodeMap.count(fromname) == 0)
238 msg="from node " + l.fromnode() + " does not exist in data link: ";
239 msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
243 //Try relative name for to node and then absolute one
244 std::string toname = currentProc->names.back()+l.tonode();
245 if(currentProc->nodeMap.count(toname) == 0)
247 //It's not a relative name. Try an absolute one (I think it's not possible)
249 if(currentProc->nodeMap.count(toname) == 0)
251 // The TO node does not exist -> error
252 msg="to node " + l.tonode() + " does not exist in data link: ";
253 msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
258 // We only link local node and other nodes (relative or absolute name in this order)
259 DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
263 _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
264 currentProc->nodeMap[toname]->getInputPort(l.toport()));
266 _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
267 currentProc->nodeMap[toname]->getInputPort(l.toport()));
271 this->logError(e.what());
281 // While loop specialization
283 template <class T=ENGINE::WhileLoop*>
284 struct whilelooptypeParser:looptypeParser<T>
286 static whilelooptypeParser<T> whileloopParser;
287 virtual void name (const std::string& name);
291 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
294 void whilelooptypeParser<T>::name (const std::string& name)
296 DEBTRACE( "while_name: " << name )
297 std::string fullname=currentProc->names.back()+name;
298 this->_cnode=theRuntime->createWhileLoop(name);
299 currentProc->nodeMap[fullname]=this->_cnode;
300 this->_cnodes.push_back(this->_cnode);
301 currentProc->names.push_back(fullname+'.');
305 T whilelooptypeParser<T>::post()
307 DEBTRACE( "while_post" << this->_cnode->getName() )
308 ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
311 this->_cnodes.pop_back();
312 currentProc->names.pop_back();
313 this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
323 // For loop specialization
325 template <class T=ENGINE::ForLoop*>
326 struct forlooptypeParser:looptypeParser<T>
328 static forlooptypeParser<T> forloopParser;
329 virtual void buildAttr(const XML_Char** attr);
330 virtual void name (const std::string& name);
331 virtual void nsteps (const int& n);
336 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
339 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
343 this->required("name",attr);
344 for (int i = 0; attr[i]; i += 2)
346 if(std::string(attr[i]) == "name")name(attr[i+1]);
347 if(std::string(attr[i]) == "state")this->state(attr[i+1]);
348 if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1]));
353 void forlooptypeParser<T>::name (const std::string& name)
355 DEBTRACE( "forloop_name: " << name );
356 std::string fullname=currentProc->names.back()+name;
357 this->_cnode=theRuntime->createForLoop(name);
358 currentProc->nodeMap[fullname]=this->_cnode;
359 this->_cnodes.push_back(this->_cnode);
360 currentProc->names.push_back(fullname+'.');
365 void forlooptypeParser<T>::nsteps (const int& n)
367 DEBTRACE( "forloop_nsteps: " << n )
369 throw Exception("Node name must be defined before nsteps");
370 ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
375 T forlooptypeParser<T>::post()
377 DEBTRACE( "forloop_post" )
379 this->_cnodes.pop_back();
380 currentProc->names.pop_back();
381 this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
389 // pseudo composed node, used to store the init or finalize node of a DynParaLoop
390 class PseudoComposedNode
393 void edSetNode(ENGINE::Node * node) { _node = node; }
394 ENGINE::Node * getNode() { return _node; }
396 // Those two methods should never be called
397 bool edAddLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
398 bool edAddDFLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
401 ENGINE::Node * _node;
404 // pseudo composed node parser specialization for DynParaLoop init and finalize nodes
405 template <class T=PseudoComposedNode*>
406 struct pseudocomposednodetypeParser:looptypeParser<T>
408 static pseudocomposednodetypeParser<T> pseudocomposednodeParser;
410 virtual void buildAttr(const XML_Char** attr)
412 this->_cnode = new PseudoComposedNode();
413 this->_cnodes.push_back(this->_cnode);
418 DEBTRACE("pseudocomposednode_post" << this->_cnode->getNode()->getName())
420 this->_cnodes.pop_back();
421 this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
425 virtual void datalink(const mylink & l)
427 throw YACS::Exception("Unexpected datalink element in DynParaLoop init or finalize node");
432 template <class T> pseudocomposednodetypeParser<T> pseudocomposednodetypeParser<T>::pseudocomposednodeParser;
438 // dynparaloop specialization
440 template <class T=ENGINE::DynParaLoop*>
441 struct dynparalooptypeParser:looptypeParser<T>
443 virtual void onStart(const XML_Char* el, const XML_Char** attr)
445 DEBTRACE( "dynparalooptypeParser::onStart: " << el )
446 std::string element(el);
447 this->maxcount("initnode",1,element);
448 this->maxcount("finalizenode",1,element);
449 if (element == "initnode" || element == "finalizenode")
451 parser* pp = &pseudocomposednodetypeParser<>::pseudocomposednodeParser;
452 this->SetUserDataAndPush(pp);
459 this->looptypeParser<T>::onStart(el, attr);
463 virtual void onEnd(const char *el, parser* child)
465 DEBTRACE( "dynparalooptypeParser::onEnd: " << el )
466 std::string element(el);
467 if (element == "initnode") initnode(((pseudocomposednodetypeParser<>*)child)->post());
468 else if (element == "finalizenode") finalizenode(((pseudocomposednodetypeParser<>*)child)->post());
469 else this->looptypeParser<T>::onEnd(el, child);
472 virtual void initnode(PseudoComposedNode * const& n)
474 DEBTRACE( "dynparaloop_initnode: " << n->getNode()->getName() )
475 this->_cnode->edSetInitNode(n->getNode());
479 virtual void finalizenode(PseudoComposedNode * const& n)
481 DEBTRACE( "dynparaloop_finalizenode: " << n->getNode()->getName() )
482 this->_cnode->edSetFinalizeNode(n->getNode());
491 // Foreach loop specialization
494 T buildFrom(ENGINE::Runtime *theRuntime, const std::string& name, ENGINE::TypeCode *type);
497 ENGINE::ForEachLoop *buildFrom<ENGINE::ForEachLoop *>(ENGINE::Runtime *theRuntime, const std::string& name, ENGINE::TypeCode *type)
498 { return theRuntime->createForEachLoop(name,type); }
501 ENGINE::ForEachLoopDyn *buildFrom<ENGINE::ForEachLoopDyn *>(ENGINE::Runtime *theRuntime, const std::string& name, ENGINE::TypeCode *type)
502 { return theRuntime->createForEachLoopDyn(name,type); }
506 struct foreachlooptypeParser:dynparalooptypeParser<T>
508 static foreachlooptypeParser<T> foreachloopParser;
510 virtual void buildAttr(const XML_Char** attr)
514 this->required("name",attr);
515 this->required("type",attr);
516 for (int i = 0; attr[i]; i += 2)
518 if(std::string(attr[i]) == "name")name(attr[i+1]);
519 if(std::string(attr[i]) == "state")this->state(attr[i+1]);
520 if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
521 if(std::string(attr[i]) == "loopWeight")weight(atof(attr[i+1]));
522 if(std::string(attr[i]) == "type")datatype(attr[i+1]);
530 this->looptypeParser<T>::pre();
532 virtual void name (const std::string& name)
534 DEBTRACE("foreach_name: " << name)
536 _fullname=currentProc->names.back()+name;
538 virtual void nbranch (const int& n)
540 DEBTRACE("foreach_nbranch: " << n )
543 virtual void weight (const double& x)
545 DEBTRACE("foreach_weight: " << x )
548 virtual void datatype (const std::string& type)
550 DEBTRACE("foreach_datatype: "<< type)
553 virtual void postAttr()
555 if(currentProc->typeMap.count(_datatype)==0)
557 //Check if the typecode is defined in the runtime
558 YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
561 std::stringstream msg;
562 msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
563 throw Exception(msg.str());
567 currentProc->typeMap[_datatype]=t;
571 this->_cnode=buildFrom<T>(theRuntime,_name,currentProc->typeMap[_datatype]);
572 //set number of branches
573 if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
574 if(_weight > 0)this->_cnode->setWeight(_weight);
575 this->_cnodes.push_back(this->_cnode);
576 currentProc->names.push_back(_fullname + '.');
580 DEBTRACE("foreach_post" << this->_cnode->getName())
582 this->_cnodes.pop_back();
583 currentProc->names.pop_back();
584 this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
589 std::string _fullname;
591 std::string _datatype;
594 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
599 // optimizer loop specialization
601 template <class T=ENGINE::OptimizerLoop*>
602 struct optimizerlooptypeParser:dynparalooptypeParser<T>
604 static optimizerlooptypeParser<T> optimizerloopParser;
606 virtual void buildAttr(const XML_Char** attr)
610 this->required("name",attr);
611 this->required("lib",attr);
612 this->required("entry",attr);
613 for (int i = 0; attr[i]; i += 2)
615 if(std::string(attr[i]) == "name")name(attr[i+1]);
616 if(std::string(attr[i]) == "state")this->state(attr[i+1]);
617 if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
618 if(std::string(attr[i]) == "loopWeight")weight(atof(attr[i+1]));
619 if(std::string(attr[i]) == "lib")lib(attr[i+1]);
620 if(std::string(attr[i]) == "entry")entry(attr[i+1]);
621 if(std::string(attr[i]) == "kind")kind(attr[i+1]);
629 this->looptypeParser<T>::pre();
631 virtual void name (const std::string& name)
633 DEBTRACE("optimizer_name: " << name)
635 _fullname=currentProc->names.back()+name;
637 virtual void lib (const std::string& name)
641 virtual void entry (const std::string& name)
645 virtual void nbranch (const int& n)
647 DEBTRACE("optimizer_nbranch: " << n )
650 virtual void weight (const double& x)
652 DEBTRACE("foreach_weight: " << x )
655 virtual void kind (const std::string& name)
659 virtual void postAttr()
661 this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
662 //set number of branches
663 if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
664 if(_weight > 0)this->_cnode->setWeight(_weight);
665 this->_cnodes.push_back(this->_cnode);
666 currentProc->names.push_back(_fullname + '.');
670 DEBTRACE("optimizer_post" << this->_cnode->getName())
672 this->_cnodes.pop_back();
673 currentProc->names.pop_back();
674 this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
680 std::string _fullname;
688 template <class T> optimizerlooptypeParser<T> optimizerlooptypeParser<T>::optimizerloopParser;
692 #include "blocParsers.hxx"
693 #include "switchParsers.hxx"
699 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
701 DEBTRACE( "looptypeParser::onStart: " << el )
702 std::string element(el);
703 this->maxcount("inline",1,element);
704 this->maxcount("sinline",1,element);
705 this->maxcount("service",1,element);
706 this->maxcount("server",1,element);
707 this->maxcount("remote",1,element);
708 this->maxcount("node",1,element);
709 this->maxcount("forloop",1,element);
710 this->maxcount("foreach",1,element);
711 this->maxcount("foreachdyn",1,element);
712 this->maxcount("optimizer",1,element);
713 this->maxcount("while",1,element);
714 this->maxcount("switch",1,element);
715 this->maxcount("bloc",1,element);
716 this->maxchoice(t3,1,element);
717 parser* pp=&parser::main_parser;
718 if(element == "property")pp=&propertytypeParser::propertyParser;
719 else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
720 else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
721 else if(element == "service")pp=&servicetypeParser<>::serviceParser;
722 else if(element == "server")pp=&servertypeParser<>::serverParser;
723 else if(element == "remote")pp=&remotetypeParser<>::remoteParser;
724 else if(element == "node")pp=&nodetypeParser<>::nodeParser;
726 else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
727 else if(element == "foreach")pp=&foreachlooptypeParser<ENGINE::ForEachLoop *>::foreachloopParser;
728 else if(element == "foreachdyn")pp=&foreachlooptypeParser<ENGINE::ForEachLoopDyn *>::foreachloopParser;
729 else if(element == "optimizer")pp=&optimizerlooptypeParser<>::optimizerloopParser;
730 else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
731 else if(element == "switch")pp=&switchtypeParser::switchParser;
732 else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
733 else if(element == "datalink")pp=&linktypeParser<>::linkParser;
734 this->SetUserDataAndPush(pp);
741 void looptypeParser<T>::onEnd(const char *el,parser* child)
743 DEBTRACE( "looptypeParser::onEnd: " << el )
744 std::string element(el);
745 if(element == "property")property(((propertytypeParser*)child)->post());
746 else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
747 else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
748 else if(element == "service")service(((servicetypeParser<>*)child)->post());
749 else if(element == "server")server(((servertypeParser<>*)child)->post());
750 else if(element == "remote")remote(((remotetypeParser<>*)child)->post());
751 else if(element == "node")node(((nodetypeParser<>*)child)->post());
753 else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
754 else if(element == "foreach")foreach(((foreachlooptypeParser<ENGINE::ForEachLoop *>*)child)->post());
755 else if(element == "foreachdyn")foreach(((foreachlooptypeParser<ENGINE::ForEachLoopDyn *>*)child)->post());
756 else if(element == "optimizer")optimizer(((optimizerlooptypeParser<>*)child)->post());
757 else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
758 else if(element == "switch")switch_(((switchtypeParser*)child)->post());
759 else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
761 else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());