]> SALOME platform Git repositories - modules/yacs.git/blob - src/yacsloader/loopParsers.hxx
Salome HOME
Merge branch 'omu/update_doc'
[modules/yacs.git] / src / yacsloader / loopParsers.hxx
1 // Copyright (C) 2006-2014  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       this->required("name",attr);
88       for (int i = 0; attr[i]; i += 2) 
89         {
90           if(std::string(attr[i]) == "name")name(attr[i+1]);
91           if(std::string(attr[i]) == "state")state(attr[i+1]);
92         }
93     }
94 template <class T>
95 void looptypeParser<T>::pre ()
96     {
97       _state="";
98       _cnode=0;
99     }
100 template <class T>
101 void looptypeParser<T>::name (const std::string& name)
102     {
103       DEBTRACE( "bloc_name: " << name );
104     }
105 template <class T>
106 void looptypeParser<T>::state (const std::string& name)
107     {
108       DEBTRACE( "bloc_state: " << name );
109       _state=name;
110     }
111 template <class T>
112 void looptypeParser<T>::property (const myprop& prop)
113     {
114       DEBTRACE( "property_set" << prop._name << prop._value );
115     }
116
117 template <class T>
118 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
119     {
120       DEBTRACE( "loop_inline" << n->getName() );
121       _cnode->edSetNode(n);
122       std::string fullname=currentProc->names.back()+ n->getName();
123       currentProc->nodeMap[fullname]=n;
124       currentProc->inlineMap[fullname]=n;
125     }
126 template <class T>
127 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
128     {
129       DEBTRACE( "loop_sinline" << n->getName() )             
130       _cnode->edSetNode(n);
131       std::string fullname=currentProc->names.back()+ n->getName();
132       currentProc->nodeMap[fullname]=n;
133       currentProc->serviceMap[fullname]=n;
134     }
135 template <class T>
136 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
137     {
138       DEBTRACE( "loop_service" << n->getName() )             
139       _cnode->edSetNode(n);
140       std::string fullname=currentProc->names.back()+ n->getName();
141       currentProc->nodeMap[fullname]=n;
142       currentProc->serviceMap[fullname]=n;
143     }
144 template <class T>
145 void looptypeParser<T>::server (ENGINE::ServerNode* const& n)
146     {
147       DEBTRACE( "loop_server" << n->getName() )             
148       _cnode->edSetNode(n);
149       std::string fullname=currentProc->names.back()+ n->getName();
150       currentProc->nodeMap[fullname]=n;
151       currentProc->inlineMap[fullname]=n;
152     }
153
154 template <class T>
155 void looptypeParser<T>::remote (YACS::ENGINE::InlineNode* const& n)
156     {
157       DEBTRACE( "loop_remote: " << n->getName() )
158       _cnode->edSetNode(n);
159       std::string fullname = currentProc->names.back()+n->getName();
160       currentProc->nodeMap[fullname]=n;
161       currentProc->inlineMap[fullname]=n;
162     }
163
164 template <class T>
165 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
166     {
167       DEBTRACE( "loop_node" << n->getName() )             
168       _cnode->edSetNode(n);
169       std::string fullname=currentProc->names.back()+ n->getName();
170       currentProc->nodeMap[fullname]=n;
171       currentProc->inlineMap[fullname]=n;
172     }
173 template <class T>
174 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
175     {
176       DEBTRACE( "loop_forloop" << b->getName() )             
177       _cnode->edSetNode(b);
178       std::string fullname=currentProc->names.back()+ b->getName();
179       currentProc->nodeMap[fullname]=b;
180     }
181 template <class T>
182 void looptypeParser<T>::foreach (ENGINE::ForEachLoop* const& b)
183     {
184       DEBTRACE("loop_foreach" << b->getName())
185       _cnode->edSetNode(b);
186       std::string fullname=currentProc->names.back()+ b->getName();
187       currentProc->nodeMap[fullname]=b;
188       fullname += ".splitter";
189       currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
190     }
191 template <class T>
192 void looptypeParser<T>::optimizer (ENGINE::OptimizerLoop* const& b)
193   {
194     DEBTRACE( "loop_optimizer: " << b->getName() );
195     _cnode->edSetNode(b);
196     std::string fullname = currentProc->names.back()+b->getName();
197     currentProc->nodeMap[fullname]=b;
198     //fullname += ".splitter";
199     //currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
200   }
201 template <class T>
202 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
203     {
204       DEBTRACE( "loop_while: " << b->getName() )             
205       _cnode->edSetNode(b);
206       std::string fullname=currentProc->names.back()+ b->getName();
207       currentProc->nodeMap[fullname]=b;
208     }
209 template <class T>
210 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
211     {
212       DEBTRACE( "loop_switch: " << b->getName() )             
213       _cnode->edSetNode(b);
214       std::string fullname=currentProc->names.back()+ b->getName();
215       currentProc->nodeMap[fullname]=b;
216     }
217 template <class T>
218 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
219     {
220       DEBTRACE( "loop_bloc " << b->getName() )             
221       _cnode->edSetNode(b);
222       std::string fullname=currentProc->names.back()+ b->getName();
223       currentProc->nodeMap[fullname]=b;
224     }
225
226 template <class T>
227 void looptypeParser<T>::datalink (const mylink& l)
228     {
229       DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
230       std::string msg;
231
232       //Try only relative name for from node
233       std::string fromname = currentProc->names.back()+l.fromnode();
234       if(currentProc->nodeMap.count(fromname) == 0)
235         {
236           msg="from node " + l.fromnode() + " does not exist in data link: ";
237           msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
238           this->logError(msg);
239           return;
240         }
241       //Try relative name for to node and then absolute one
242       std::string toname = currentProc->names.back()+l.tonode();
243       if(currentProc->nodeMap.count(toname) == 0)
244         {
245           //It's not a relative name. Try an absolute one (I think it's not possible)
246           toname=l.tonode();
247           if(currentProc->nodeMap.count(toname) == 0)
248             {
249               // The TO node does not exist -> error
250               msg="to node " + l.tonode() + " does not exist in data link: ";
251               msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
252               this->logError(msg);
253               return;
254             }
255         }
256       // We only link local node and other nodes (relative or absolute name in this order)
257       DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
258       try
259         {
260           if (l.withControl())
261             _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
262                                 currentProc->nodeMap[toname]->getInputPort(l.toport()));
263           else
264             _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
265                               currentProc->nodeMap[toname]->getInputPort(l.toport()));
266         }
267       catch(Exception& e)
268         {
269             this->logError(e.what());
270         }
271     }
272
273
274 }
275
276 namespace YACS
277 {
278
279   // While loop specialization
280
281 template <class T=ENGINE::WhileLoop*>
282 struct whilelooptypeParser:looptypeParser<T>
283 {
284   static whilelooptypeParser<T> whileloopParser;
285   virtual void name (const std::string& name);
286   virtual T post();
287 };
288
289 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
290
291 template <class T>
292 void whilelooptypeParser<T>::name (const std::string& name)
293     {
294       DEBTRACE( "while_name: " << name )             
295       std::string fullname=currentProc->names.back()+name;
296       this->_cnode=theRuntime->createWhileLoop(name);
297       currentProc->nodeMap[fullname]=this->_cnode;
298       this->_cnodes.push_back(this->_cnode);
299       currentProc->names.push_back(fullname+'.');
300     }
301
302 template <class T>
303 T whilelooptypeParser<T>::post()
304     {
305       DEBTRACE( "while_post" << this->_cnode->getName() )             
306       ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
307       cond->edInit(true);
308       T b=this->_cnode;
309       this->_cnodes.pop_back();
310       currentProc->names.pop_back();
311       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
312       return b;
313     }
314 }
315
316
317
318
319 namespace YACS
320 {
321   // For loop specialization
322
323 template <class T=ENGINE::ForLoop*>
324 struct forlooptypeParser:looptypeParser<T>
325 {
326   static forlooptypeParser<T> forloopParser;
327   virtual void buildAttr(const XML_Char** attr);
328   virtual void name (const std::string& name);
329   virtual void nsteps (const int& n);
330   virtual T post();
331   int _nsteps;
332 };
333
334 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
335
336 template <class T>
337 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
338     {
339       this->required("name",attr);
340       for (int i = 0; attr[i]; i += 2) 
341         {
342           if(std::string(attr[i]) == "name")name(attr[i+1]);
343           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
344           if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1]));
345         }
346     }
347
348 template <class T>
349   void forlooptypeParser<T>::name (const std::string& name)
350     {
351       DEBTRACE( "forloop_name: " << name );
352       std::string fullname=currentProc->names.back()+name;
353       this->_cnode=theRuntime->createForLoop(name);
354       currentProc->nodeMap[fullname]=this->_cnode;
355       this->_cnodes.push_back(this->_cnode);
356       currentProc->names.push_back(fullname+'.');
357       _nsteps=0;
358     }
359
360 template <class T>
361 void forlooptypeParser<T>::nsteps (const int& n)
362     {
363       DEBTRACE( "forloop_nsteps: " << n )             
364       if(!this->_cnode)
365           throw Exception("Node name must be defined before nsteps");
366       ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
367       iNbTimes->edInit(n);
368     }
369
370 template <class T>
371    T forlooptypeParser<T>::post()
372     {
373       DEBTRACE( "forloop_post" )             
374       T b=this->_cnode;
375       this->_cnodes.pop_back();
376       currentProc->names.pop_back();
377       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
378       return b;
379     }
380
381 }
382
383 namespace YACS
384 {
385 // pseudo composed node, used to store the init or finalize node of a DynParaLoop
386 class PseudoComposedNode
387 {
388 public:
389   void edSetNode(ENGINE::Node * node) { _node = node; }
390   ENGINE::Node * getNode() { return _node; }
391
392   // Those two methods should never be called
393   bool edAddLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
394   bool edAddDFLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
395
396 protected:
397   ENGINE::Node * _node;
398 };
399
400 // pseudo composed node parser specialization for DynParaLoop init and finalize nodes
401 template <class T=PseudoComposedNode*>
402 struct pseudocomposednodetypeParser:looptypeParser<T>
403 {
404   static pseudocomposednodetypeParser<T> pseudocomposednodeParser;
405
406   virtual void buildAttr(const XML_Char** attr)
407     {
408       this->_cnode = new PseudoComposedNode();
409       this->_cnodes.push_back(this->_cnode);
410     }
411
412   virtual T post()
413     {
414       DEBTRACE("pseudocomposednode_post" << this->_cnode->getNode()->getName())
415       T b = this->_cnode;
416       this->_cnodes.pop_back();
417       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
418       return b;
419     }
420
421   virtual void datalink(const mylink & l)
422     {
423       throw YACS::Exception("Unexpected datalink element in DynParaLoop init or finalize node");
424     }
425
426 };
427
428 template <class T> pseudocomposednodetypeParser<T> pseudocomposednodetypeParser<T>::pseudocomposednodeParser;
429
430 }
431
432 namespace YACS
433 {
434 // dynparaloop specialization
435
436 template <class T=ENGINE::DynParaLoop*>
437 struct dynparalooptypeParser:looptypeParser<T>
438 {
439   virtual void onStart(const XML_Char* el, const XML_Char** attr)
440     {
441       DEBTRACE( "dynparalooptypeParser::onStart: " << el )
442       std::string element(el);
443       this->maxcount("initnode",1,element);
444       this->maxcount("finalizenode",1,element);
445       if (element == "initnode" || element == "finalizenode")
446         {
447           parser* pp = &pseudocomposednodetypeParser<>::pseudocomposednodeParser;
448           this->SetUserDataAndPush(pp);
449           pp->init();
450           pp->pre();
451           pp->buildAttr(attr);
452         }
453       else
454         {
455           this->looptypeParser<T>::onStart(el, attr);
456         }
457     }
458
459   virtual void onEnd(const char *el, parser* child)
460     {
461       DEBTRACE( "dynparalooptypeParser::onEnd: " << el )
462       std::string element(el);
463       if (element == "initnode") initnode(((pseudocomposednodetypeParser<>*)child)->post());
464       else if (element == "finalizenode") finalizenode(((pseudocomposednodetypeParser<>*)child)->post());
465       else this->looptypeParser<T>::onEnd(el, child);
466     }
467
468   virtual void initnode(PseudoComposedNode * const& n)
469     {
470       DEBTRACE( "dynparaloop_initnode: " << n->getNode()->getName() )
471       this->_cnode->edSetInitNode(n->getNode());
472       delete n;
473     }
474
475   virtual void finalizenode(PseudoComposedNode * const& n)
476     {
477       DEBTRACE( "dynparaloop_finalizenode: " << n->getNode()->getName() )
478       this->_cnode->edSetFinalizeNode(n->getNode());
479       delete n;
480     }
481 };
482
483 }
484
485 namespace YACS
486 {
487   // Foreach loop specialization
488
489 template <class T=ENGINE::ForEachLoop*>
490 struct foreachlooptypeParser:dynparalooptypeParser<T>
491 {
492   static foreachlooptypeParser<T> foreachloopParser;
493
494   virtual void buildAttr(const XML_Char** attr)
495     {
496       this->required("name",attr);
497       this->required("type",attr);
498       for (int i = 0; attr[i]; i += 2) 
499         {
500           if(std::string(attr[i]) == "name")name(attr[i+1]);
501           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
502           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
503           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
504         }
505       postAttr();
506     }
507   virtual void pre ()
508     {
509       _nbranch=0;
510       this->looptypeParser<T>::pre();
511     }
512   virtual void name (const std::string& name)
513     {
514       DEBTRACE("foreach_name: " << name)
515       _name=name;
516       _fullname=currentProc->names.back()+name;
517     }
518   virtual void nbranch (const int& n)
519     {
520       DEBTRACE("foreach_nbranch: " << n )
521       _nbranch=n;
522     }
523   virtual void datatype (const std::string& type)
524     {
525       DEBTRACE("foreach_datatype: "<< type)
526       _datatype=type;
527     }
528   virtual void postAttr()
529     {
530       if(currentProc->typeMap.count(_datatype)==0)
531       {
532         //Check if the typecode is defined in the runtime
533         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
534         if(t==0)
535         {
536           std::stringstream msg;
537           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
538           throw Exception(msg.str());
539         }
540         else
541         {
542           currentProc->typeMap[_datatype]=t;
543           t->incrRef();
544         }
545       }
546       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
547       //set number of branches
548       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
549       this->_cnodes.push_back(this->_cnode);
550       currentProc->names.push_back(_fullname + '.');
551     }
552   virtual T post()
553     {
554       DEBTRACE("foreach_post" << this->_cnode->getName())
555       T b=this->_cnode;
556       this->_cnodes.pop_back();
557       currentProc->names.pop_back();
558       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
559       return b;
560     }
561   int _nbranch;
562   std::string _fullname;
563   std::string _name;
564   std::string _datatype;
565 };
566
567 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
568
569 }
570
571 namespace YACS
572 {
573   // optimizer loop specialization
574
575 template <class T=ENGINE::OptimizerLoop*>
576 struct optimizerlooptypeParser:dynparalooptypeParser<T>
577 {
578   static optimizerlooptypeParser<T> optimizerloopParser;
579
580   virtual void buildAttr(const XML_Char** attr)
581     {
582       this->required("name",attr);
583       this->required("lib",attr);
584       this->required("entry",attr);
585       for (int i = 0; attr[i]; i += 2)
586         {
587           if(std::string(attr[i]) == "name")name(attr[i+1]);
588           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
589           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
590           if(std::string(attr[i]) == "lib")lib(attr[i+1]);
591           if(std::string(attr[i]) == "entry")entry(attr[i+1]);
592           if(std::string(attr[i]) == "kind")kind(attr[i+1]);
593         }
594       postAttr();
595     }
596   virtual void pre ()
597     {
598       _nbranch=0;
599       this->looptypeParser<T>::pre();
600     }
601   virtual void name (const std::string& name)
602     {
603       DEBTRACE("optimizer_name: " << name)
604       _name=name;
605       _fullname=currentProc->names.back()+name;
606     }
607   virtual void lib (const std::string& name)
608     {
609       _lib=name;
610     }
611   virtual void entry (const std::string& name)
612     {
613       _entry=name;
614     }
615   virtual void nbranch (const int& n)
616     {
617       DEBTRACE("optimizer_nbranch: " << n )
618       _nbranch=n;
619     }
620   virtual void kind (const std::string& name)
621     {
622       _kind=name;
623     }
624   virtual void postAttr()
625     {
626       this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
627       //set number of branches
628       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
629       this->_cnodes.push_back(this->_cnode);
630       currentProc->names.push_back(_fullname + '.');
631     }
632   virtual T post()
633     {
634       DEBTRACE("optimizer_post" << this->_cnode->getName())
635       T b=this->_cnode;
636       this->_cnodes.pop_back();
637       currentProc->names.pop_back();
638       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
639       return b;
640     }
641
642   int _nbranch;
643   std::string _fullname;
644   std::string _name;
645   std::string _entry;
646   std::string _kind;
647   std::string _lib;
648
649 };
650
651 template <class T> optimizerlooptypeParser<T> optimizerlooptypeParser<T>::optimizerloopParser;
652
653 }
654
655 #include "blocParsers.hxx"
656 #include "switchParsers.hxx"
657
658 namespace YACS
659 {
660
661 template <class T>
662 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
663 {
664   DEBTRACE( "looptypeParser::onStart: " << el )
665   std::string element(el);
666   this->maxcount("inline",1,element);
667   this->maxcount("sinline",1,element);
668   this->maxcount("service",1,element);
669   this->maxcount("server",1,element);
670   this->maxcount("remote",1,element);
671   this->maxcount("node",1,element);
672   this->maxcount("forloop",1,element);
673   this->maxcount("foreach",1,element);
674   this->maxcount("optimizer",1,element);
675   this->maxcount("while",1,element);
676   this->maxcount("switch",1,element);
677   this->maxcount("bloc",1,element);
678   this->maxchoice(t3,1,element);
679   parser* pp=&parser::main_parser;
680   if(element == "property")pp=&propertytypeParser::propertyParser;
681   else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
682   else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
683   else if(element == "service")pp=&servicetypeParser<>::serviceParser;
684   else if(element == "server")pp=&servertypeParser<>::serverParser;
685   else if(element == "remote")pp=&remotetypeParser<>::remoteParser;
686   else if(element == "node")pp=&nodetypeParser<>::nodeParser;
687
688   else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
689   else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
690   else if(element == "optimizer")pp=&optimizerlooptypeParser<>::optimizerloopParser;
691   else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
692   else if(element == "switch")pp=&switchtypeParser::switchParser;
693   else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
694   else if(element == "datalink")pp=&linktypeParser<>::linkParser;
695   this->SetUserDataAndPush(pp);
696   pp->init();
697   pp->pre();
698   pp->buildAttr(attr);
699 }
700
701 template <class T>
702 void looptypeParser<T>::onEnd(const char *el,parser* child)
703 {
704   DEBTRACE( "looptypeParser::onEnd: " << el )
705   std::string element(el);
706   if(element == "property")property(((propertytypeParser*)child)->post());
707   else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
708   else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
709   else if(element == "service")service(((servicetypeParser<>*)child)->post());
710   else if(element == "server")server(((servertypeParser<>*)child)->post());
711   else if(element == "remote")remote(((remotetypeParser<>*)child)->post());
712   else if(element == "node")node(((nodetypeParser<>*)child)->post());
713
714   else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
715   else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
716   else if(element == "optimizer")optimizer(((optimizerlooptypeParser<>*)child)->post());
717   else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
718   else if(element == "switch")switch_(((switchtypeParser*)child)->post());
719   else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
720
721   else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());
722 }
723
724 }
725 #endif