Salome HOME
Merge branch 'master' of https://git.salome-platform.org/git/modules/yacs
[modules/yacs.git] / src / yacsloader / loopParsers.hxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #ifndef _LOOPPARSER_HXX_
21 #define _LOOPPARSER_HXX_
22
23 #include "parserBase.hxx"
24
25 #include "Bloc.hxx"
26 #include "Proc.hxx"
27 #include "Logger.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"
36 #include "Switch.hxx"
37 #include "ForEachLoop.hxx"
38 #include "OptimizerLoop.hxx"
39
40 #include <vector>
41 #include <string>
42 #include <sstream>
43
44 namespace YACS
45 {
46
47 template <class T=ENGINE::Loop*>
48 struct looptypeParser:parser
49 {
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);
53   virtual void pre ();
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::ForEachLoop* 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);
70   std::string _state;
71   T _cnode;
72   std::vector<T> _cnodes;
73 };
74
75 }
76
77 namespace YACS
78 {
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 !!!
81   //
82   static std::string t3[]={"inline","sinline","service","server", "remote", "node","forloop","foreach","optimizer","while","switch","bloc",""};
83
84 template <class T>
85 void looptypeParser<T>::buildAttr(const XML_Char** attr)
86     {
87       if (!attr)
88         return;
89       this->required("name",attr);
90       for (int i = 0; attr[i]; i += 2) 
91         {
92           if(std::string(attr[i]) == "name")name(attr[i+1]);
93           if(std::string(attr[i]) == "state")state(attr[i+1]);
94         }
95     }
96 template <class T>
97 void looptypeParser<T>::pre ()
98     {
99       _state="";
100       _cnode=0;
101     }
102 template <class T>
103 void looptypeParser<T>::name (const std::string& name)
104     {
105       DEBTRACE( "bloc_name: " << name );
106     }
107 template <class T>
108 void looptypeParser<T>::state (const std::string& name)
109     {
110       DEBTRACE( "bloc_state: " << name );
111       _state=name;
112     }
113 template <class T>
114 void looptypeParser<T>::property (const myprop& prop)
115     {
116       DEBTRACE( "property_set" << prop._name << prop._value );
117     }
118
119 template <class T>
120 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
121     {
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;
127     }
128 template <class T>
129 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
130     {
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;
136     }
137 template <class T>
138 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
139     {
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;
145     }
146 template <class T>
147 void looptypeParser<T>::server (ENGINE::ServerNode* const& n)
148     {
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;
154     }
155
156 template <class T>
157 void looptypeParser<T>::remote (YACS::ENGINE::InlineNode* const& n)
158     {
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;
164     }
165
166 template <class T>
167 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
168     {
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;
174     }
175 template <class T>
176 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
177     {
178       DEBTRACE( "loop_forloop" << b->getName() )             
179       _cnode->edSetNode(b);
180       std::string fullname=currentProc->names.back()+ b->getName();
181       currentProc->nodeMap[fullname]=b;
182     }
183 template <class T>
184 void looptypeParser<T>::foreach (ENGINE::ForEachLoop* const& b)
185     {
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");
192     }
193 template <class T>
194 void looptypeParser<T>::optimizer (ENGINE::OptimizerLoop* const& b)
195   {
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");
202   }
203 template <class T>
204 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
205     {
206       DEBTRACE( "loop_while: " << b->getName() )             
207       _cnode->edSetNode(b);
208       std::string fullname=currentProc->names.back()+ b->getName();
209       currentProc->nodeMap[fullname]=b;
210     }
211 template <class T>
212 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
213     {
214       DEBTRACE( "loop_switch: " << b->getName() )             
215       _cnode->edSetNode(b);
216       std::string fullname=currentProc->names.back()+ b->getName();
217       currentProc->nodeMap[fullname]=b;
218     }
219 template <class T>
220 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
221     {
222       DEBTRACE( "loop_bloc " << b->getName() )             
223       _cnode->edSetNode(b);
224       std::string fullname=currentProc->names.back()+ b->getName();
225       currentProc->nodeMap[fullname]=b;
226     }
227
228 template <class T>
229 void looptypeParser<T>::datalink (const mylink& l)
230     {
231       DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
232       std::string msg;
233
234       //Try only relative name for from node
235       std::string fromname = currentProc->names.back()+l.fromnode();
236       if(currentProc->nodeMap.count(fromname) == 0)
237         {
238           msg="from node " + l.fromnode() + " does not exist in data link: ";
239           msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
240           this->logError(msg);
241           return;
242         }
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)
246         {
247           //It's not a relative name. Try an absolute one (I think it's not possible)
248           toname=l.tonode();
249           if(currentProc->nodeMap.count(toname) == 0)
250             {
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()+")";
254               this->logError(msg);
255               return;
256             }
257         }
258       // We only link local node and other nodes (relative or absolute name in this order)
259       DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
260       try
261         {
262           if (l.withControl())
263             _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
264                                 currentProc->nodeMap[toname]->getInputPort(l.toport()));
265           else
266             _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
267                               currentProc->nodeMap[toname]->getInputPort(l.toport()));
268         }
269       catch(Exception& e)
270         {
271             this->logError(e.what());
272         }
273     }
274
275
276 }
277
278 namespace YACS
279 {
280
281   // While loop specialization
282
283 template <class T=ENGINE::WhileLoop*>
284 struct whilelooptypeParser:looptypeParser<T>
285 {
286   static whilelooptypeParser<T> whileloopParser;
287   virtual void name (const std::string& name);
288   virtual T post();
289 };
290
291 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
292
293 template <class T>
294 void whilelooptypeParser<T>::name (const std::string& name)
295     {
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+'.');
302     }
303
304 template <class T>
305 T whilelooptypeParser<T>::post()
306     {
307       DEBTRACE( "while_post" << this->_cnode->getName() )             
308       ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
309       cond->edInit(true);
310       T b=this->_cnode;
311       this->_cnodes.pop_back();
312       currentProc->names.pop_back();
313       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
314       return b;
315     }
316 }
317
318
319
320
321 namespace YACS
322 {
323   // For loop specialization
324
325 template <class T=ENGINE::ForLoop*>
326 struct forlooptypeParser:looptypeParser<T>
327 {
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);
332   virtual T post();
333   int _nsteps;
334 };
335
336 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
337
338 template <class T>
339 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
340     {
341       if (!attr)
342         return;
343       this->required("name",attr);
344       for (int i = 0; attr[i]; i += 2) 
345         {
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]));
349         }
350     }
351
352 template <class T>
353   void forlooptypeParser<T>::name (const std::string& name)
354     {
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+'.');
361       _nsteps=0;
362     }
363
364 template <class T>
365 void forlooptypeParser<T>::nsteps (const int& n)
366     {
367       DEBTRACE( "forloop_nsteps: " << n )             
368       if(!this->_cnode)
369           throw Exception("Node name must be defined before nsteps");
370       ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
371       iNbTimes->edInit(n);
372     }
373
374 template <class T>
375    T forlooptypeParser<T>::post()
376     {
377       DEBTRACE( "forloop_post" )             
378       T b=this->_cnode;
379       this->_cnodes.pop_back();
380       currentProc->names.pop_back();
381       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
382       return b;
383     }
384
385 }
386
387 namespace YACS
388 {
389 // pseudo composed node, used to store the init or finalize node of a DynParaLoop
390 class PseudoComposedNode
391 {
392 public:
393   void edSetNode(ENGINE::Node * node) { _node = node; }
394   ENGINE::Node * getNode() { return _node; }
395
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); }
399
400 protected:
401   ENGINE::Node * _node;
402 };
403
404 // pseudo composed node parser specialization for DynParaLoop init and finalize nodes
405 template <class T=PseudoComposedNode*>
406 struct pseudocomposednodetypeParser:looptypeParser<T>
407 {
408   static pseudocomposednodetypeParser<T> pseudocomposednodeParser;
409
410   virtual void buildAttr(const XML_Char** attr)
411     {
412       this->_cnode = new PseudoComposedNode();
413       this->_cnodes.push_back(this->_cnode);
414     }
415
416   virtual T post()
417     {
418       DEBTRACE("pseudocomposednode_post" << this->_cnode->getNode()->getName())
419       T b = this->_cnode;
420       this->_cnodes.pop_back();
421       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
422       return b;
423     }
424
425   virtual void datalink(const mylink & l)
426     {
427       throw YACS::Exception("Unexpected datalink element in DynParaLoop init or finalize node");
428     }
429
430 };
431
432 template <class T> pseudocomposednodetypeParser<T> pseudocomposednodetypeParser<T>::pseudocomposednodeParser;
433
434 }
435
436 namespace YACS
437 {
438 // dynparaloop specialization
439
440 template <class T=ENGINE::DynParaLoop*>
441 struct dynparalooptypeParser:looptypeParser<T>
442 {
443   virtual void onStart(const XML_Char* el, const XML_Char** attr)
444     {
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")
450         {
451           parser* pp = &pseudocomposednodetypeParser<>::pseudocomposednodeParser;
452           this->SetUserDataAndPush(pp);
453           pp->init();
454           pp->pre();
455           pp->buildAttr(attr);
456         }
457       else
458         {
459           this->looptypeParser<T>::onStart(el, attr);
460         }
461     }
462
463   virtual void onEnd(const char *el, parser* child)
464     {
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);
470     }
471
472   virtual void initnode(PseudoComposedNode * const& n)
473     {
474       DEBTRACE( "dynparaloop_initnode: " << n->getNode()->getName() )
475       this->_cnode->edSetInitNode(n->getNode());
476       delete n;
477     }
478
479   virtual void finalizenode(PseudoComposedNode * const& n)
480     {
481       DEBTRACE( "dynparaloop_finalizenode: " << n->getNode()->getName() )
482       this->_cnode->edSetFinalizeNode(n->getNode());
483       delete n;
484     }
485 };
486
487 }
488
489 namespace YACS
490 {
491   // Foreach loop specialization
492
493 template <class T=ENGINE::ForEachLoop*>
494 struct foreachlooptypeParser:dynparalooptypeParser<T>
495 {
496   static foreachlooptypeParser<T> foreachloopParser;
497
498   virtual void buildAttr(const XML_Char** attr)
499     {
500       if (!attr)
501         return;
502       this->required("name",attr);
503       this->required("type",attr);
504       for (int i = 0; attr[i]; i += 2) 
505         {
506           if(std::string(attr[i]) == "name")name(attr[i+1]);
507           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
508           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
509           if(std::string(attr[i]) == "weight")weight(atof(attr[i+1]));
510           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
511         }
512       postAttr();
513     }
514   virtual void pre ()
515     {
516       _nbranch=0;
517       _weight=1;
518       this->looptypeParser<T>::pre();
519     }
520   virtual void name (const std::string& name)
521     {
522       DEBTRACE("foreach_name: " << name)
523       _name=name;
524       _fullname=currentProc->names.back()+name;
525     }
526   virtual void nbranch (const int& n)
527     {
528       DEBTRACE("foreach_nbranch: " << n )
529       _nbranch=n;
530     }
531   virtual void weight (const double& x)
532     {
533       DEBTRACE("foreach_weight: " << x )
534       _weight=x;
535     }
536   virtual void datatype (const std::string& type)
537     {
538       DEBTRACE("foreach_datatype: "<< type)
539       _datatype=type;
540     }
541   virtual void postAttr()
542     {
543       if(currentProc->typeMap.count(_datatype)==0)
544       {
545         //Check if the typecode is defined in the runtime
546         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
547         if(t==0)
548         {
549           std::stringstream msg;
550           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
551           throw Exception(msg.str());
552         }
553         else
554         {
555           currentProc->typeMap[_datatype]=t;
556           t->incrRef();
557         }
558       }
559       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
560       //set number of branches
561       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
562       this->_cnode->setWeight(_weight);
563       this->_cnodes.push_back(this->_cnode);
564       currentProc->names.push_back(_fullname + '.');
565     }
566   virtual T post()
567     {
568       DEBTRACE("foreach_post" << this->_cnode->getName())
569       T b=this->_cnode;
570       this->_cnodes.pop_back();
571       currentProc->names.pop_back();
572       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
573       return b;
574     }
575   int _nbranch;
576   double _weight;
577   std::string _fullname;
578   std::string _name;
579   std::string _datatype;
580 };
581
582 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
583
584 }
585
586 namespace YACS
587 {
588   // optimizer loop specialization
589
590 template <class T=ENGINE::OptimizerLoop*>
591 struct optimizerlooptypeParser:dynparalooptypeParser<T>
592 {
593   static optimizerlooptypeParser<T> optimizerloopParser;
594
595   virtual void buildAttr(const XML_Char** attr)
596     {
597       if (!attr)
598         return;
599       this->required("name",attr);
600       this->required("lib",attr);
601       this->required("entry",attr);
602       for (int i = 0; attr[i]; i += 2)
603         {
604           if(std::string(attr[i]) == "name")name(attr[i+1]);
605           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
606           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
607           if(std::string(attr[i]) == "weight")weight(atof(attr[i+1]));
608           if(std::string(attr[i]) == "lib")lib(attr[i+1]);
609           if(std::string(attr[i]) == "entry")entry(attr[i+1]);
610           if(std::string(attr[i]) == "kind")kind(attr[i+1]);
611         }
612       postAttr();
613     }
614   virtual void pre ()
615     {
616       _nbranch=0;
617       _weight=1;
618       this->looptypeParser<T>::pre();
619     }
620   virtual void name (const std::string& name)
621     {
622       DEBTRACE("optimizer_name: " << name)
623       _name=name;
624       _fullname=currentProc->names.back()+name;
625     }
626   virtual void lib (const std::string& name)
627     {
628       _lib=name;
629     }
630   virtual void entry (const std::string& name)
631     {
632       _entry=name;
633     }
634   virtual void nbranch (const int& n)
635     {
636       DEBTRACE("optimizer_nbranch: " << n )
637       _nbranch=n;
638     }
639   virtual void weight (const double& x)
640     {
641       DEBTRACE("foreach_weight: " << x )
642       _weight=x;
643     }
644   virtual void kind (const std::string& name)
645     {
646       _kind=name;
647     }
648   virtual void postAttr()
649     {
650       this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
651       //set number of branches
652       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
653       this->_cnode->setWeight(_weight);
654       this->_cnodes.push_back(this->_cnode);
655       currentProc->names.push_back(_fullname + '.');
656     }
657   virtual T post()
658     {
659       DEBTRACE("optimizer_post" << this->_cnode->getName())
660       T b=this->_cnode;
661       this->_cnodes.pop_back();
662       currentProc->names.pop_back();
663       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
664       return b;
665     }
666
667   int _nbranch;
668   double _weight;
669   std::string _fullname;
670   std::string _name;
671   std::string _entry;
672   std::string _kind;
673   std::string _lib;
674
675 };
676
677 template <class T> optimizerlooptypeParser<T> optimizerlooptypeParser<T>::optimizerloopParser;
678
679 }
680
681 #include "blocParsers.hxx"
682 #include "switchParsers.hxx"
683
684 namespace YACS
685 {
686
687 template <class T>
688 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
689 {
690   DEBTRACE( "looptypeParser::onStart: " << el )
691   std::string element(el);
692   this->maxcount("inline",1,element);
693   this->maxcount("sinline",1,element);
694   this->maxcount("service",1,element);
695   this->maxcount("server",1,element);
696   this->maxcount("remote",1,element);
697   this->maxcount("node",1,element);
698   this->maxcount("forloop",1,element);
699   this->maxcount("foreach",1,element);
700   this->maxcount("optimizer",1,element);
701   this->maxcount("while",1,element);
702   this->maxcount("switch",1,element);
703   this->maxcount("bloc",1,element);
704   this->maxchoice(t3,1,element);
705   parser* pp=&parser::main_parser;
706   if(element == "property")pp=&propertytypeParser::propertyParser;
707   else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
708   else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
709   else if(element == "service")pp=&servicetypeParser<>::serviceParser;
710   else if(element == "server")pp=&servertypeParser<>::serverParser;
711   else if(element == "remote")pp=&remotetypeParser<>::remoteParser;
712   else if(element == "node")pp=&nodetypeParser<>::nodeParser;
713
714   else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
715   else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
716   else if(element == "optimizer")pp=&optimizerlooptypeParser<>::optimizerloopParser;
717   else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
718   else if(element == "switch")pp=&switchtypeParser::switchParser;
719   else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
720   else if(element == "datalink")pp=&linktypeParser<>::linkParser;
721   this->SetUserDataAndPush(pp);
722   pp->init();
723   pp->pre();
724   pp->buildAttr(attr);
725 }
726
727 template <class T>
728 void looptypeParser<T>::onEnd(const char *el,parser* child)
729 {
730   DEBTRACE( "looptypeParser::onEnd: " << el )
731   std::string element(el);
732   if(element == "property")property(((propertytypeParser*)child)->post());
733   else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
734   else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
735   else if(element == "service")service(((servicetypeParser<>*)child)->post());
736   else if(element == "server")server(((servertypeParser<>*)child)->post());
737   else if(element == "remote")remote(((remotetypeParser<>*)child)->post());
738   else if(element == "node")node(((nodetypeParser<>*)child)->post());
739
740   else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
741   else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
742   else if(element == "optimizer")optimizer(((optimizerlooptypeParser<>*)child)->post());
743   else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
744   else if(element == "switch")switch_(((switchtypeParser*)child)->post());
745   else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
746
747   else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());
748 }
749
750 }
751 #endif