1 // Copyright (C) 2006-2008 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.
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
19 #ifndef _LOOPPARSER_HXX_
20 #define _LOOPPARSER_HXX_
22 #include "parserBase.hxx"
27 #include "Exception.hxx"
28 #include "InlineNode.hxx"
29 #include "ServiceNode.hxx"
30 #include "ServiceInlineNode.hxx"
31 #include "OutputDataStreamPort.hxx"
32 #include "InputDataStreamPort.hxx"
33 #include "ForLoop.hxx"
34 #include "WhileLoop.hxx"
36 #include "ForEachLoop.hxx"
45 template <class T=ENGINE::Loop*>
46 struct looptypeParser:parser
48 void onStart(const XML_Char* el, const XML_Char** attr);
49 void onEnd(const char *el,parser* child);
50 virtual void buildAttr(const XML_Char** attr);
52 virtual void name (const std::string& name);
53 virtual void state (const std::string& name);
54 virtual void property (const myprop& prop);
55 virtual void inline_ (ENGINE::InlineNode* const& n);
56 virtual void sinline (ENGINE::ServiceInlineNode* const& n);
57 virtual void service (ENGINE::ServiceNode* const& n);
58 virtual void node (ENGINE::InlineNode* const& n);
59 virtual void forloop (ENGINE::ForLoop* const& b);
60 virtual void foreach (ENGINE::ForEachLoop* const& b);
61 virtual void while_ (ENGINE::WhileLoop* const& b);
62 virtual void switch_ (ENGINE::Switch* const& b);
63 virtual void bloc (ENGINE::Bloc* const& b);
64 virtual void datalink (const mylink& l);
67 std::vector<T> _cnodes;
74 // A loop can contain forloop, whileloop or foreachloop
75 // We must respect the order : definition of loop, then while, for, .. and then onStart, onEnd for loop !!!
77 static std::string t3[]={"inline","sinline","service","node","forloop","foreach","while","switch","bloc",""};
80 void looptypeParser<T>::buildAttr(const XML_Char** attr)
82 this->required("name",attr);
83 for (int i = 0; attr[i]; i += 2)
85 if(std::string(attr[i]) == "name")name(attr[i+1]);
86 if(std::string(attr[i]) == "state")state(attr[i+1]);
90 void looptypeParser<T>::pre ()
96 void looptypeParser<T>::name (const std::string& name)
98 DEBTRACE( "bloc_name: " << name );
101 void looptypeParser<T>::state (const std::string& name)
103 DEBTRACE( "bloc_state: " << name );
107 void looptypeParser<T>::property (const myprop& prop)
109 DEBTRACE( "property_set" << prop._name << prop._value );
113 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
115 DEBTRACE( "loop_inline" << n->getName() );
116 _cnode->edSetNode(n);
117 std::string fullname=currentProc->names.back()+ n->getName();
118 currentProc->nodeMap[fullname]=n;
119 currentProc->inlineMap[fullname]=n;
122 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
124 DEBTRACE( "loop_sinline" << n->getName() )
125 _cnode->edSetNode(n);
126 std::string fullname=currentProc->names.back()+ n->getName();
127 currentProc->nodeMap[fullname]=n;
128 currentProc->serviceMap[fullname]=n;
131 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
133 DEBTRACE( "loop_service" << n->getName() )
134 _cnode->edSetNode(n);
135 std::string fullname=currentProc->names.back()+ n->getName();
136 currentProc->nodeMap[fullname]=n;
137 currentProc->serviceMap[fullname]=n;
140 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
142 DEBTRACE( "loop_node" << n->getName() )
143 _cnode->edSetNode(n);
144 std::string fullname=currentProc->names.back()+ n->getName();
145 currentProc->nodeMap[fullname]=n;
146 currentProc->inlineMap[fullname]=n;
149 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
151 DEBTRACE( "loop_forloop" << b->getName() )
152 _cnode->edSetNode(b);
153 std::string fullname=currentProc->names.back()+ b->getName();
154 currentProc->nodeMap[fullname]=b;
157 void looptypeParser<T>::foreach (ENGINE::ForEachLoop* const& b)
159 DEBTRACE("loop_foreach" << b->getName())
160 _cnode->edSetNode(b);
161 std::string fullname=currentProc->names.back()+ b->getName();
162 currentProc->nodeMap[fullname]=b;
163 fullname += ".splitter";
164 currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
167 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
169 DEBTRACE( "loop_while: " << b->getName() )
170 _cnode->edSetNode(b);
171 std::string fullname=currentProc->names.back()+ b->getName();
172 currentProc->nodeMap[fullname]=b;
175 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
177 DEBTRACE( "loop_switch: " << b->getName() )
178 _cnode->edSetNode(b);
179 std::string fullname=currentProc->names.back()+ b->getName();
180 currentProc->nodeMap[fullname]=b;
183 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
185 DEBTRACE( "loop_bloc " << b->getName() )
186 _cnode->edSetNode(b);
187 std::string fullname=currentProc->names.back()+ b->getName();
188 currentProc->nodeMap[fullname]=b;
192 void looptypeParser<T>::datalink (const mylink& l)
194 DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
197 //Try only relative name for from node
198 std::string fromname = currentProc->names.back()+l.fromnode();
199 if(currentProc->nodeMap.count(fromname) == 0)
201 msg="from node " + l.fromnode() + " does not exist in data link: ";
202 msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
206 //Try relative name for to node and then absolute one
207 std::string toname = currentProc->names.back()+l.tonode();
208 if(currentProc->nodeMap.count(toname) == 0)
210 //It's not a relative name. Try an absolute one (I think it's not possible)
212 if(currentProc->nodeMap.count(toname) == 0)
214 // The TO node does not exist -> error
215 msg="to node " + l.tonode() + " does not exist in data link: ";
216 msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
221 // We only link local node and other nodes (relative or absolute name in this order)
222 DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
226 _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
227 currentProc->nodeMap[toname]->getInputPort(l.toport()));
229 _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
230 currentProc->nodeMap[toname]->getInputPort(l.toport()));
234 this->logError(e.what());
244 // While loop specialization
246 template <class T=ENGINE::WhileLoop*>
247 struct whilelooptypeParser:looptypeParser<T>
249 static whilelooptypeParser<T> whileloopParser;
250 virtual void name (const std::string& name);
254 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
257 void whilelooptypeParser<T>::name (const std::string& name)
259 DEBTRACE( "while_name: " << name )
260 std::string fullname=currentProc->names.back()+name;
261 this->_cnode=theRuntime->createWhileLoop(name);
262 currentProc->nodeMap[fullname]=this->_cnode;
263 this->_cnodes.push_back(this->_cnode);
264 currentProc->names.push_back(fullname+'.');
268 T whilelooptypeParser<T>::post()
270 DEBTRACE( "while_post" << this->_cnode->getName() )
271 ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
274 this->_cnodes.pop_back();
275 currentProc->names.pop_back();
276 this->_cnode=this->_cnodes.back();
286 // For loop specialization
288 template <class T=ENGINE::ForLoop*>
289 struct forlooptypeParser:looptypeParser<T>
291 static forlooptypeParser<T> forloopParser;
292 virtual void buildAttr(const XML_Char** attr);
293 virtual void name (const std::string& name);
294 virtual void nsteps (const int& n);
299 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
302 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
304 this->required("name",attr);
305 for (int i = 0; attr[i]; i += 2)
307 if(std::string(attr[i]) == "name")name(attr[i+1]);
308 if(std::string(attr[i]) == "state")this->state(attr[i+1]);
309 if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1]));
314 void forlooptypeParser<T>::name (const std::string& name)
316 DEBTRACE( "forloop_name: " << name );
317 std::string fullname=currentProc->names.back()+name;
318 this->_cnode=theRuntime->createForLoop(name);
319 currentProc->nodeMap[fullname]=this->_cnode;
320 this->_cnodes.push_back(this->_cnode);
321 currentProc->names.push_back(fullname+'.');
326 void forlooptypeParser<T>::nsteps (const int& n)
328 DEBTRACE( "forloop_nsteps: " << n )
330 throw Exception("Node name must be defined before nsteps");
331 ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
336 T forlooptypeParser<T>::post()
338 DEBTRACE( "forloop_post" )
340 this->_cnodes.pop_back();
341 currentProc->names.pop_back();
342 this->_cnode=this->_cnodes.back();
350 // Foreach loop specialization
352 template <class T=ENGINE::ForEachLoop*>
353 struct foreachlooptypeParser:looptypeParser<T>
355 static foreachlooptypeParser<T> foreachloopParser;
357 virtual void buildAttr(const XML_Char** attr)
359 this->required("name",attr);
360 this->required("type",attr);
361 for (int i = 0; attr[i]; i += 2)
363 if(std::string(attr[i]) == "name")name(attr[i+1]);
364 if(std::string(attr[i]) == "state")this->state(attr[i+1]);
365 if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
366 if(std::string(attr[i]) == "type")datatype(attr[i+1]);
373 this->looptypeParser<T>::pre();
375 virtual void name (const std::string& name)
377 DEBTRACE("foreach_name: " << name)
379 _fullname=currentProc->names.back()+name;
381 virtual void nbranch (const int& n)
383 DEBTRACE("foreach_nbranch: " << n )
386 virtual void datatype (const std::string& type)
388 DEBTRACE("foreach_datatype: "<< type)
391 virtual void postAttr()
393 if(currentProc->typeMap.count(_datatype)==0)
395 //Check if the typecode is defined in the runtime
396 YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
399 std::stringstream msg;
400 msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
401 throw Exception(msg.str());
405 currentProc->typeMap[_datatype]=t;
409 this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
410 //set number of branches
411 if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
412 this->_cnodes.push_back(this->_cnode);
413 currentProc->names.push_back(_fullname + '.');
417 DEBTRACE("foreach_post" << this->_cnode->getName())
419 this->_cnodes.pop_back();
420 currentProc->names.pop_back();
421 if(this->_cnodes.size() == 0)
424 this->_cnode=this->_cnodes.back();
428 std::string _fullname;
430 std::string _datatype;
433 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
437 #include "blocParsers.hxx"
438 #include "switchParsers.hxx"
444 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
446 DEBTRACE( "looptypeParser::onStart: " << el )
447 std::string element(el);
448 this->maxcount("inline",1,element);
449 this->maxcount("sinline",1,element);
450 this->maxcount("service",1,element);
451 this->maxcount("node",1,element);
452 this->maxcount("forloop",1,element);
453 this->maxcount("foreach",1,element);
454 this->maxcount("while",1,element);
455 this->maxcount("switch",1,element);
456 this->maxcount("bloc",1,element);
457 this->maxchoice(t3,1,element);
458 parser* pp=&parser::main_parser;
459 if(element == "property")pp=&propertytypeParser::propertyParser;
460 else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
461 else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
462 else if(element == "service")pp=&servicetypeParser<>::serviceParser;
463 else if(element == "node")pp=&nodetypeParser<>::nodeParser;
465 else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
466 else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
467 else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
468 else if(element == "switch")pp=&switchtypeParser::switchParser;
469 else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
470 else if(element == "datalink")pp=&linktypeParser<>::linkParser;
471 this->SetUserDataAndPush(pp);
478 void looptypeParser<T>::onEnd(const char *el,parser* child)
480 DEBTRACE( "looptypeParser::onEnd: " << el )
481 std::string element(el);
482 if(element == "property")property(((propertytypeParser*)child)->post());
483 else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
484 else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
485 else if(element == "service")service(((servicetypeParser<>*)child)->post());
486 else if(element == "node")node(((nodetypeParser<>*)child)->post());
488 else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
489 else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
490 else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
491 else if(element == "switch")switch_(((switchtypeParser*)child)->post());
492 else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
494 else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());