Salome HOME
Merge branch 'omu/update_doc_77'
[modules/yacs.git] / src / yacsloader / loopParsers.hxx
1 // Copyright (C) 2006-2015  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]) == "type")datatype(attr[i+1]);
510         }
511       postAttr();
512     }
513   virtual void pre ()
514     {
515       _nbranch=0;
516       this->looptypeParser<T>::pre();
517     }
518   virtual void name (const std::string& name)
519     {
520       DEBTRACE("foreach_name: " << name)
521       _name=name;
522       _fullname=currentProc->names.back()+name;
523     }
524   virtual void nbranch (const int& n)
525     {
526       DEBTRACE("foreach_nbranch: " << n )
527       _nbranch=n;
528     }
529   virtual void datatype (const std::string& type)
530     {
531       DEBTRACE("foreach_datatype: "<< type)
532       _datatype=type;
533     }
534   virtual void postAttr()
535     {
536       if(currentProc->typeMap.count(_datatype)==0)
537       {
538         //Check if the typecode is defined in the runtime
539         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
540         if(t==0)
541         {
542           std::stringstream msg;
543           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
544           throw Exception(msg.str());
545         }
546         else
547         {
548           currentProc->typeMap[_datatype]=t;
549           t->incrRef();
550         }
551       }
552       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
553       //set number of branches
554       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
555       this->_cnodes.push_back(this->_cnode);
556       currentProc->names.push_back(_fullname + '.');
557     }
558   virtual T post()
559     {
560       DEBTRACE("foreach_post" << this->_cnode->getName())
561       T b=this->_cnode;
562       this->_cnodes.pop_back();
563       currentProc->names.pop_back();
564       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
565       return b;
566     }
567   int _nbranch;
568   std::string _fullname;
569   std::string _name;
570   std::string _datatype;
571 };
572
573 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
574
575 }
576
577 namespace YACS
578 {
579   // optimizer loop specialization
580
581 template <class T=ENGINE::OptimizerLoop*>
582 struct optimizerlooptypeParser:dynparalooptypeParser<T>
583 {
584   static optimizerlooptypeParser<T> optimizerloopParser;
585
586   virtual void buildAttr(const XML_Char** attr)
587     {
588       if (!attr)
589         return;
590       this->required("name",attr);
591       this->required("lib",attr);
592       this->required("entry",attr);
593       for (int i = 0; attr[i]; i += 2)
594         {
595           if(std::string(attr[i]) == "name")name(attr[i+1]);
596           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
597           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
598           if(std::string(attr[i]) == "lib")lib(attr[i+1]);
599           if(std::string(attr[i]) == "entry")entry(attr[i+1]);
600           if(std::string(attr[i]) == "kind")kind(attr[i+1]);
601         }
602       postAttr();
603     }
604   virtual void pre ()
605     {
606       _nbranch=0;
607       this->looptypeParser<T>::pre();
608     }
609   virtual void name (const std::string& name)
610     {
611       DEBTRACE("optimizer_name: " << name)
612       _name=name;
613       _fullname=currentProc->names.back()+name;
614     }
615   virtual void lib (const std::string& name)
616     {
617       _lib=name;
618     }
619   virtual void entry (const std::string& name)
620     {
621       _entry=name;
622     }
623   virtual void nbranch (const int& n)
624     {
625       DEBTRACE("optimizer_nbranch: " << n )
626       _nbranch=n;
627     }
628   virtual void kind (const std::string& name)
629     {
630       _kind=name;
631     }
632   virtual void postAttr()
633     {
634       this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
635       //set number of branches
636       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
637       this->_cnodes.push_back(this->_cnode);
638       currentProc->names.push_back(_fullname + '.');
639     }
640   virtual T post()
641     {
642       DEBTRACE("optimizer_post" << this->_cnode->getName())
643       T b=this->_cnode;
644       this->_cnodes.pop_back();
645       currentProc->names.pop_back();
646       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
647       return b;
648     }
649
650   int _nbranch;
651   std::string _fullname;
652   std::string _name;
653   std::string _entry;
654   std::string _kind;
655   std::string _lib;
656
657 };
658
659 template <class T> optimizerlooptypeParser<T> optimizerlooptypeParser<T>::optimizerloopParser;
660
661 }
662
663 #include "blocParsers.hxx"
664 #include "switchParsers.hxx"
665
666 namespace YACS
667 {
668
669 template <class T>
670 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
671 {
672   DEBTRACE( "looptypeParser::onStart: " << el )
673   std::string element(el);
674   this->maxcount("inline",1,element);
675   this->maxcount("sinline",1,element);
676   this->maxcount("service",1,element);
677   this->maxcount("server",1,element);
678   this->maxcount("remote",1,element);
679   this->maxcount("node",1,element);
680   this->maxcount("forloop",1,element);
681   this->maxcount("foreach",1,element);
682   this->maxcount("optimizer",1,element);
683   this->maxcount("while",1,element);
684   this->maxcount("switch",1,element);
685   this->maxcount("bloc",1,element);
686   this->maxchoice(t3,1,element);
687   parser* pp=&parser::main_parser;
688   if(element == "property")pp=&propertytypeParser::propertyParser;
689   else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
690   else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
691   else if(element == "service")pp=&servicetypeParser<>::serviceParser;
692   else if(element == "server")pp=&servertypeParser<>::serverParser;
693   else if(element == "remote")pp=&remotetypeParser<>::remoteParser;
694   else if(element == "node")pp=&nodetypeParser<>::nodeParser;
695
696   else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
697   else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
698   else if(element == "optimizer")pp=&optimizerlooptypeParser<>::optimizerloopParser;
699   else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
700   else if(element == "switch")pp=&switchtypeParser::switchParser;
701   else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
702   else if(element == "datalink")pp=&linktypeParser<>::linkParser;
703   this->SetUserDataAndPush(pp);
704   pp->init();
705   pp->pre();
706   pp->buildAttr(attr);
707 }
708
709 template <class T>
710 void looptypeParser<T>::onEnd(const char *el,parser* child)
711 {
712   DEBTRACE( "looptypeParser::onEnd: " << el )
713   std::string element(el);
714   if(element == "property")property(((propertytypeParser*)child)->post());
715   else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
716   else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
717   else if(element == "service")service(((servicetypeParser<>*)child)->post());
718   else if(element == "server")server(((servertypeParser<>*)child)->post());
719   else if(element == "remote")remote(((remotetypeParser<>*)child)->post());
720   else if(element == "node")node(((nodetypeParser<>*)child)->post());
721
722   else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
723   else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
724   else if(element == "optimizer")optimizer(((optimizerlooptypeParser<>*)child)->post());
725   else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
726   else if(element == "switch")switch_(((switchtypeParser*)child)->post());
727   else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
728
729   else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());
730 }
731
732 }
733 #endif