9a9c388bb58f07d55b412c1d5b5120c43568f767
[external/ragel.git] / ragel / xmlcodegen.cpp
1 /*
2  *  Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  * 
12  *  Ragel is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  * 
17  *  You should have received a copy of the GNU General Public License
18  *  along with Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22
23 #include "ragel.h"
24 #include "xmlcodegen.h"
25 #include "parsedata.h"
26 #include "fsmgraph.h"
27 #include "gendata.h"
28 #include "inputdata.h"
29 #include <string.h>
30 #include "rlparse.h"
31 #include "version.h"
32
33 using namespace std;
34
35 GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm )
36 :
37         fsmName(fsmName),
38         pd(pd),
39         fsm(fsm),
40         nextActionTableId(0)
41 {
42 }
43
44 void GenBase::appendTrans( TransListVect &outList, Key lowKey, 
45                 Key highKey, TransAp *trans )
46 {
47         if ( trans->toState != 0 || trans->actionTable.length() > 0 )
48                 outList.append( TransEl( lowKey, highKey, trans ) );
49 }
50
51 void GenBase::reduceActionTables()
52 {
53         /* Reduce the actions tables to a set. */
54         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
55                 RedActionTable *actionTable = 0;
56
57                 /* Reduce To State Actions. */
58                 if ( st->toStateActionTable.length() > 0 ) {
59                         if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
60                                 actionTable->id = nextActionTableId++;
61                 }
62
63                 /* Reduce From State Actions. */
64                 if ( st->fromStateActionTable.length() > 0 ) {
65                         if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
66                                 actionTable->id = nextActionTableId++;
67                 }
68
69                 /* Reduce EOF actions. */
70                 if ( st->eofActionTable.length() > 0 ) {
71                         if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
72                                 actionTable->id = nextActionTableId++;
73                 }
74
75                 /* Loop the transitions and reduce their actions. */
76                 for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
77                         if ( trans->actionTable.length() > 0 ) {
78                                 if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
79                                         actionTable->id = nextActionTableId++;
80                         }
81                 }
82         }
83 }
84
85 XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, std::ostream &out )
86 :
87         GenBase(fsmName, pd, fsm),
88         out(out)
89 {
90 }
91
92
93 void XMLCodeGen::writeActionList()
94 {
95         /* Determine which actions to write. */
96         int nextActionId = 0;
97         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
98                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
99                         act->actionId = nextActionId++;
100         }
101
102         /* Write the list. */
103         out << "    <action_list length=\"" << nextActionId << "\">\n";
104         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
105                 if ( act->actionId >= 0 )
106                         writeAction( act );
107         }
108         out << "    </action_list>\n";
109 }
110
111 void XMLCodeGen::writeActionTableList()
112 {
113         /* Must first order the action tables based on their id. */
114         int numTables = nextActionTableId;
115         RedActionTable **tables = new RedActionTable*[numTables];
116         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
117                 tables[at->id] = at;
118
119         out << "    <action_table_list length=\"" << numTables << "\">\n";
120         for ( int t = 0; t < numTables; t++ ) {
121                 out << "      <action_table id=\"" << t << "\" length=\"" << 
122                                 tables[t]->key.length() << "\">";
123                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
124                         out << atel->value->actionId;
125                         if ( ! atel.last() )
126                                 out << " ";
127                 }
128                 out << "</action_table>\n";
129         }
130         out << "    </action_table_list>\n";
131
132         delete[] tables;
133 }
134
135 void XMLCodeGen::writeKey( Key key )
136 {
137         if ( keyOps->isSigned )
138                 out << key.getVal();
139         else
140                 out << (unsigned long) key.getVal();
141 }
142
143 void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
144 {
145         /* First reduce the action. */
146         RedActionTable *actionTable = 0;
147         if ( trans->actionTable.length() > 0 )
148                 actionTable = actionTableMap.find( trans->actionTable );
149
150         /* Write the transition. */
151         out << "        <t>";
152         writeKey( lowKey );
153         out << " ";
154         writeKey( highKey );
155
156         if ( trans->toState != 0 )
157                 out << " " << trans->toState->alg.stateNum;
158         else
159                 out << " x";
160
161         if ( actionTable != 0 )
162                 out << " " << actionTable->id;
163         else
164                 out << " x";
165         out << "</t>\n";
166 }
167
168 void XMLCodeGen::writeTransList( StateAp *state )
169 {
170         TransListVect outList;
171
172         /* If there is only are no ranges the task is simple. */
173         if ( state->outList.length() > 0 ) {
174                 /* Loop each source range. */
175                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
176                         /* Reduce the transition. If it reduced to anything then add it. */
177                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
178                 }
179         }
180
181         out << "      <trans_list length=\"" << outList.length() << "\">\n";
182         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
183                 writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
184         out << "      </trans_list>\n";
185 }
186
187 void XMLCodeGen::writeEofTrans( StateAp *state )
188 {
189         RedActionTable *eofActions = 0;
190         if ( state->eofActionTable.length() > 0 )
191                 eofActions = actionTableMap.find( state->eofActionTable );
192         
193         /* The <eof_t> is used when there is an eof target, otherwise the eof
194          * action goes into state actions. */
195         if ( state->eofTarget != 0 ) {
196                 out << "      <eof_t>" << state->eofTarget->alg.stateNum;
197
198                 if ( eofActions != 0 )
199                         out << " " << eofActions->id;
200                 else
201                         out << " x"; 
202
203                 out << "</eof_t>" << endl;
204         }
205 }
206
207 void XMLCodeGen::writeText( InlineItem *item )
208 {
209         if ( item->prev == 0 || item->prev->type != InlineItem::Text )
210                 out << "<text>";
211         xmlEscapeHost( out, item->data, strlen(item->data) );
212         if ( item->next == 0 || item->next->type != InlineItem::Text )
213                 out << "</text>";
214 }
215
216 void XMLCodeGen::writeGoto( InlineItem *item )
217 {
218         if ( pd->generatingSectionSubset )
219                 out << "<goto>-1</goto>";
220         else {
221                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
222                 out << "<goto>" << targ->value->alg.stateNum << "</goto>";
223         }
224 }
225
226 void XMLCodeGen::writeCall( InlineItem *item )
227 {
228         if ( pd->generatingSectionSubset )
229                 out << "<call>-1</call>";
230         else {
231                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
232                 out << "<call>" << targ->value->alg.stateNum << "</call>";
233         }
234 }
235
236 void XMLCodeGen::writeNext( InlineItem *item )
237 {
238         if ( pd->generatingSectionSubset )
239                 out << "<next>-1</next>";
240         else {
241                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
242                 out << "<next>" << targ->value->alg.stateNum << "</next>";
243         }
244 }
245
246 void XMLCodeGen::writeGotoExpr( InlineItem *item )
247 {
248         out << "<goto_expr>";
249         writeInlineList( item->children );
250         out << "</goto_expr>";
251 }
252
253 void XMLCodeGen::writeCallExpr( InlineItem *item )
254 {
255         out << "<call_expr>";
256         writeInlineList( item->children );
257         out << "</call_expr>";
258 }
259
260 void XMLCodeGen::writeNextExpr( InlineItem *item )
261 {
262         out << "<next_expr>";
263         writeInlineList( item->children );
264         out << "</next_expr>";
265 }
266
267 void XMLCodeGen::writeEntry( InlineItem *item )
268 {
269         if ( pd->generatingSectionSubset )
270                 out << "<entry>-1</entry>";
271         else {
272                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
273                 out << "<entry>" << targ->value->alg.stateNum << "</entry>";
274         }
275 }
276
277 void XMLCodeGen::writeActionExec( InlineItem *item )
278 {
279         out << "<exec>";
280         writeInlineList( item->children );
281         out << "</exec>";
282 }
283
284 void XMLCodeGen::writeLmOnLast( InlineItem *item )
285 {
286         out << "<set_tokend>1</set_tokend>";
287
288         if ( item->longestMatchPart->action != 0 ) {
289                 out << "<sub_action>";
290                 writeInlineList( item->longestMatchPart->action->inlineList );
291                 out << "</sub_action>";
292         }
293 }
294
295 void XMLCodeGen::writeLmOnNext( InlineItem *item )
296 {
297         out << "<set_tokend>0</set_tokend>";
298         out << "<hold></hold>";
299
300         if ( item->longestMatchPart->action != 0 ) {
301                 out << "<sub_action>";
302                 writeInlineList( item->longestMatchPart->action->inlineList );
303                 out << "</sub_action>";
304         }
305 }
306
307 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
308 {
309         out << "<exec><get_tokend></get_tokend></exec>";
310
311         if ( item->longestMatchPart->action != 0 ) {
312                 out << "<sub_action>";
313                 writeInlineList( item->longestMatchPart->action->inlineList );
314                 out << "</sub_action>";
315         }
316 }
317
318 void XMLCodeGen::writeLmSwitch( InlineItem *item )
319 {
320         LongestMatch *longestMatch = item->longestMatch;
321         out << "<lm_switch>\n";
322
323         /* We can't put the <exec> here because we may need to handle the error
324          * case and in that case p should not be changed. Instead use a default
325          * label in the switch to adjust p when user actions are not set. An id of
326          * -1 indicates the default. */
327
328         if ( longestMatch->lmSwitchHandlesError ) {
329                 /* If the switch handles error then we should have also forced the
330                  * error state. */
331                 assert( fsm->errState != 0 );
332
333                 out << "        <sub_action id=\"0\">";
334                 out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
335                 out << "</sub_action>\n";
336         }
337         
338         bool needDefault = false;
339         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
340                 if ( lmi->inLmSelect ) {
341                         if ( lmi->action == 0 )
342                                 needDefault = true;
343                         else {
344                                 /* Open the action. Write it with the context that sets up _p 
345                                  * when doing control flow changes from inside the machine. */
346                                 out << "        <sub_action id=\"" << lmi->longestMatchId << "\">";
347                                 out << "<exec><get_tokend></get_tokend></exec>";
348                                 writeInlineList( lmi->action->inlineList );
349                                 out << "</sub_action>\n";
350                         }
351                 }
352         }
353
354         if ( needDefault ) {
355                 out << "        <sub_action id=\"-1\"><exec><get_tokend>"
356                                 "</get_tokend></exec></sub_action>\n";
357         }
358
359         out << "    </lm_switch>";
360 }
361
362 void XMLCodeGen::writeInlineList( InlineList *inlineList )
363 {
364         for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
365                 switch ( item->type ) {
366                 case InlineItem::Text:
367                         writeText( item );
368                         break;
369                 case InlineItem::Goto:
370                         writeGoto( item );
371                         break;
372                 case InlineItem::GotoExpr:
373                         writeGotoExpr( item );
374                         break;
375                 case InlineItem::Call:
376                         writeCall( item );
377                         break;
378                 case InlineItem::CallExpr:
379                         writeCallExpr( item );
380                         break;
381                 case InlineItem::Next:
382                         writeNext( item );
383                         break;
384                 case InlineItem::NextExpr:
385                         writeNextExpr( item );
386                         break;
387                 case InlineItem::Break:
388                         out << "<break></break>";
389                         break;
390                 case InlineItem::Ret: 
391                         out << "<ret></ret>";
392                         break;
393                 case InlineItem::PChar:
394                         out << "<pchar></pchar>";
395                         break;
396                 case InlineItem::Char: 
397                         out << "<char></char>";
398                         break;
399                 case InlineItem::Curs: 
400                         out << "<curs></curs>";
401                         break;
402                 case InlineItem::Targs: 
403                         out << "<targs></targs>";
404                         break;
405                 case InlineItem::Entry:
406                         writeEntry( item );
407                         break;
408
409                 case InlineItem::Hold:
410                         out << "<hold></hold>";
411                         break;
412                 case InlineItem::Exec:
413                         writeActionExec( item );
414                         break;
415
416                 case InlineItem::LmSetActId:
417                         out << "<set_act>" << 
418                                         item->longestMatchPart->longestMatchId << 
419                                         "</set_act>";
420                         break;
421                 case InlineItem::LmSetTokEnd:
422                         out << "<set_tokend>1</set_tokend>";
423                         break;
424
425                 case InlineItem::LmOnLast:
426                         writeLmOnLast( item );
427                         break;
428                 case InlineItem::LmOnNext:
429                         writeLmOnNext( item );
430                         break;
431                 case InlineItem::LmOnLagBehind:
432                         writeLmOnLagBehind( item );
433                         break;
434                 case InlineItem::LmSwitch: 
435                         writeLmSwitch( item );
436                         break;
437
438                 case InlineItem::LmInitAct:
439                         out << "<init_act></init_act>";
440                         break;
441                 case InlineItem::LmInitTokStart:
442                         out << "<init_tokstart></init_tokstart>";
443                         break;
444                 case InlineItem::LmSetTokStart:
445                         out << "<set_tokstart></set_tokstart>";
446                         break;
447                 }
448         }
449 }
450
451 BackendGen::BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, CodeGenData *cgd )
452 :
453         GenBase(fsmName, pd, fsm),
454         cgd(cgd)
455 {
456 }
457
458
459 void BackendGen::makeText( GenInlineList *outList, InlineItem *item )
460 {
461         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text );
462         inlineItem->data = item->data;
463
464         outList->append( inlineItem );
465 }
466
467 void BackendGen::makeTargetItem( GenInlineList *outList, NameInst *nameTarg, 
468                 GenInlineItem::Type type )
469 {
470         long targetState;
471         if ( pd->generatingSectionSubset )
472                 targetState = -1;
473         else {
474                 EntryMapEl *targ = fsm->entryPoints.find( nameTarg->id );
475                 targetState = targ->value->alg.stateNum;
476         }
477
478         /* Make the item. */
479         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
480         inlineItem->targId = targetState;
481         outList->append( inlineItem );
482 }
483
484 /* Make a sublist item with a given type. */
485 void BackendGen::makeSubList( GenInlineList *outList, 
486                 InlineList *inlineList, GenInlineItem::Type type )
487 {
488         /* Fill the sub list. */
489         GenInlineList *subList = new GenInlineList;
490         makeGenInlineList( subList, inlineList );
491
492         /* Make the item. */
493         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
494         inlineItem->children = subList;
495         outList->append( inlineItem );
496 }
497
498 void BackendGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
499 {
500         makeSetTokend( outList, 1 );
501
502         if ( item->longestMatchPart->action != 0 ) {
503                 makeSubList( outList, 
504                                 item->longestMatchPart->action->inlineList, 
505                                 GenInlineItem::SubAction );
506         }
507 }
508
509 void BackendGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
510 {
511         makeSetTokend( outList, 0 );
512         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
513
514         if ( item->longestMatchPart->action != 0 ) {
515                 makeSubList( outList, 
516                         item->longestMatchPart->action->inlineList,
517                         GenInlineItem::SubAction );
518         }
519 }
520
521 void BackendGen::makeExecGetTokend( GenInlineList *outList )
522 {
523         /* Make the Exec item. */
524         GenInlineItem *execItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
525         execItem->children = new GenInlineList;
526
527         /* Make the GetTokEnd */
528         GenInlineItem *getTokend = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
529         execItem->children->append( getTokend );
530
531         outList->append( execItem );
532 }
533
534 void BackendGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
535 {
536         /* Jump to the tokend. */
537         makeExecGetTokend( outList );
538
539         if ( item->longestMatchPart->action != 0 ) {
540                 makeSubList( outList,
541                         item->longestMatchPart->action->inlineList,
542                         GenInlineItem::SubAction );
543         }
544 }
545
546 void BackendGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
547 {
548         GenInlineItem *lmSwitch = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
549         GenInlineList *lmList = lmSwitch->children = new GenInlineList;
550         LongestMatch *longestMatch = item->longestMatch;
551
552         /* We can't put the <exec> here because we may need to handle the error
553          * case and in that case p should not be changed. Instead use a default
554          * label in the switch to adjust p when user actions are not set. An id of
555          * -1 indicates the default. */
556
557         if ( longestMatch->lmSwitchHandlesError ) {
558                 /* If the switch handles error then we should have also forced the
559                  * error state. */
560                 assert( fsm->errState != 0 );
561
562                 GenInlineItem *errCase = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
563                 errCase->lmId = 0;
564                 errCase->children = new GenInlineList;
565
566                 /* Make the item. */
567                 GenInlineItem *gotoItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
568                 gotoItem->targId = fsm->errState->alg.stateNum;
569                 errCase->children->append( gotoItem );
570
571                 lmList->append( errCase );
572         }
573         
574         bool needDefault = false;
575         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
576                 if ( lmi->inLmSelect ) {
577                         if ( lmi->action == 0 )
578                                 needDefault = true;
579                         else {
580                                 /* Open the action. Write it with the context that sets up _p 
581                                  * when doing control flow changes from inside the machine. */
582                                 GenInlineItem *lmCase = new GenInlineItem( InputLoc(), 
583                                                 GenInlineItem::SubAction );
584                                 lmCase->lmId = lmi->longestMatchId;
585                                 lmCase->children = new GenInlineList;
586
587                                 makeExecGetTokend( lmCase->children );
588                                 makeGenInlineList( lmCase->children, lmi->action->inlineList );
589
590                                 lmList->append( lmCase );
591                         }
592                 }
593         }
594
595         if ( needDefault ) {
596                 GenInlineItem *defCase = new GenInlineItem( InputLoc(), 
597                                 GenInlineItem::SubAction );
598                 defCase->lmId = -1;
599                 defCase->children = new GenInlineList;
600
601                 makeExecGetTokend( defCase->children );
602
603                 lmList->append( defCase );
604         }
605
606         outList->append( lmSwitch );
607 }
608
609 void BackendGen::makeSetTokend( GenInlineList *outList, long offset )
610 {
611         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
612         inlineItem->offset = offset;
613         outList->append( inlineItem );
614 }
615
616 void BackendGen::makeSetAct( GenInlineList *outList, long lmId )
617 {
618         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
619         inlineItem->lmId = lmId;
620         outList->append( inlineItem );
621 }
622
623 void BackendGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
624 {
625         for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
626                 switch ( item->type ) {
627                 case InlineItem::Text:
628                         makeText( outList, item );
629                         break;
630                 case InlineItem::Goto:
631                         makeTargetItem( outList, item->nameTarg, GenInlineItem::Goto );
632                         break;
633                 case InlineItem::GotoExpr:
634                         makeSubList( outList, item->children, GenInlineItem::GotoExpr );
635                         break;
636                 case InlineItem::Call:
637                         makeTargetItem( outList, item->nameTarg, GenInlineItem::Call );
638                         break;
639                 case InlineItem::CallExpr:
640                         makeSubList( outList, item->children, GenInlineItem::CallExpr );
641                         break;
642                 case InlineItem::Next:
643                         makeTargetItem( outList, item->nameTarg, GenInlineItem::Next );
644                         break;
645                 case InlineItem::NextExpr:
646                         makeSubList( outList, item->children, GenInlineItem::NextExpr );
647                         break;
648                 case InlineItem::Break:
649                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Break ) );
650                         break;
651                 case InlineItem::Ret: 
652                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret ) );
653                         break;
654                 case InlineItem::PChar:
655                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar ) );
656                         break;
657                 case InlineItem::Char: 
658                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Char ) );
659                         break;
660                 case InlineItem::Curs: 
661                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs ) );
662                         break;
663                 case InlineItem::Targs: 
664                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs ) );
665                         break;
666                 case InlineItem::Entry:
667                         makeTargetItem( outList, item->nameTarg, GenInlineItem::Entry );
668                         break;
669
670                 case InlineItem::Hold:
671                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
672                         break;
673                 case InlineItem::Exec:
674                         makeSubList( outList, item->children, GenInlineItem::Exec );
675                         break;
676
677                 case InlineItem::LmSetActId:
678                         makeSetAct( outList, item->longestMatchPart->longestMatchId );
679                         break;
680                 case InlineItem::LmSetTokEnd:
681                         makeSetTokend( outList, 1 );
682                         break;
683
684                 case InlineItem::LmOnLast:
685                         makeLmOnLast( outList, item );
686                         break;
687                 case InlineItem::LmOnNext:
688                         makeLmOnNext( outList, item );
689                         break;
690                 case InlineItem::LmOnLagBehind:
691                         makeLmOnLagBehind( outList, item );
692                         break;
693                 case InlineItem::LmSwitch: 
694                         makeLmSwitch( outList, item );
695                         break;
696
697                 case InlineItem::LmInitAct:
698                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ) );
699                         break;
700                 case InlineItem::LmInitTokStart:
701                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ) );
702                         break;
703                 case InlineItem::LmSetTokStart:
704                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ) );
705                         cgd->hasLongestMatch = true;
706                         break;
707                 }
708         }
709 }
710
711
712 void XMLCodeGen::writeAction( Action *action )
713 {
714         out << "      <action id=\"" << action->actionId << "\"";
715         if ( action->name != 0 ) 
716                 out << " name=\"" << action->name << "\"";
717         out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
718         writeInlineList( action->inlineList );
719         out << "</action>\n";
720 }
721
722 void xmlEscapeHost( std::ostream &out, char *data, long len )
723 {
724         char *end = data + len;
725         while ( data != end ) {
726                 switch ( *data ) {
727                 case '<': out << "&lt;"; break;
728                 case '>': out << "&gt;"; break;
729                 case '&': out << "&amp;"; break;
730                 default: out << *data; break;
731                 }
732                 data += 1;
733         }
734 }
735
736 void XMLCodeGen::writeStateActions( StateAp *state )
737 {
738         RedActionTable *toStateActions = 0;
739         if ( state->toStateActionTable.length() > 0 )
740                 toStateActions = actionTableMap.find( state->toStateActionTable );
741
742         RedActionTable *fromStateActions = 0;
743         if ( state->fromStateActionTable.length() > 0 )
744                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
745
746         /* EOF actions go out here only if the state has no eof target. If it has
747          * an eof target then an eof transition will be used instead. */
748         RedActionTable *eofActions = 0;
749         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
750                 eofActions = actionTableMap.find( state->eofActionTable );
751         
752         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
753                 out << "      <state_actions>";
754                 if ( toStateActions != 0 )
755                         out << toStateActions->id;
756                 else
757                         out << "x";
758
759                 if ( fromStateActions != 0 )
760                         out << " " << fromStateActions->id;
761                 else
762                         out << " x";
763
764                 if ( eofActions != 0 )
765                         out << " " << eofActions->id;
766                 else
767                         out << " x";
768
769                 out << "</state_actions>\n";
770         }
771 }
772
773 void XMLCodeGen::writeStateConditions( StateAp *state )
774 {
775         if ( state->stateCondList.length() > 0 ) {
776                 out << "      <cond_list length=\"" << state->stateCondList.length() << "\">\n";
777                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
778                         out << "        <c>";
779                         writeKey( scdi->lowKey );
780                         out << " ";
781                         writeKey( scdi->highKey );
782                         out << " ";
783                         out << scdi->condSpace->condSpaceId;
784                         out << "</c>\n";
785                 }
786                 out << "      </cond_list>\n";
787         }
788 }
789
790 void XMLCodeGen::writeStateList()
791 {
792         /* Write the list of states. */
793         out << "    <state_list length=\"" << fsm->stateList.length() << "\">\n";
794         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
795                 out << "      <state id=\"" << st->alg.stateNum << "\"";
796                 if ( st->isFinState() )
797                         out << " final=\"t\"";
798                 out << ">\n";
799
800                 writeStateActions( st );
801                 writeEofTrans( st );
802                 writeStateConditions( st );
803                 writeTransList( st );
804
805                 out << "      </state>\n";
806
807                 if ( !st.last() )
808                         out << "\n";
809         }
810         out << "    </state_list>\n";
811 }
812
813 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
814 {
815         bool written = false;
816         if ( nameInst->parent != 0 )
817                 written = writeNameInst( nameInst->parent );
818         
819         if ( nameInst->name != 0 ) {
820                 if ( written )
821                         out << '_';
822                 out << nameInst->name;
823                 written = true;
824         }
825
826         return written;
827 }
828
829 void XMLCodeGen::writeEntryPoints()
830 {
831         /* List of entry points other than start state. */
832         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
833                 out << "    <entry_points";
834                 if ( pd->lmRequiresErrorState )
835                         out << " error=\"t\"";
836                 out << ">\n";
837                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
838                         /* Get the name instantiation from nameIndex. */
839                         NameInst *nameInst = pd->nameIndex[en->key];
840                         StateAp *state = en->value;
841                         out << "      <entry name=\"";
842                         writeNameInst( nameInst );
843                         out << "\">" << state->alg.stateNum << "</entry>\n";
844                 }
845                 out << "    </entry_points>\n";
846         }
847 }
848
849 void XMLCodeGen::writeMachine()
850 {
851         /* Open the machine. */
852         out << "  <machine>\n"; 
853         
854         /* Action tables. */
855         reduceActionTables();
856
857         writeActionList();
858         writeActionTableList();
859         writeConditions();
860
861         /* Start state. */
862         out << "    <start_state>" << fsm->startState->alg.stateNum << 
863                         "</start_state>\n";
864         
865         /* Error state. */
866         if ( fsm->errState != 0 ) {
867                 out << "    <error_state>" << fsm->errState->alg.stateNum << 
868                         "</error_state>\n";
869         }
870
871         writeEntryPoints();
872         writeStateList();
873
874         out << "  </machine>\n";
875 }
876
877
878 void XMLCodeGen::writeConditions()
879 {
880         if ( condData->condSpaceMap.length() > 0 ) {
881                 long nextCondSpaceId = 0;
882                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
883                         cs->condSpaceId = nextCondSpaceId++;
884
885                 out << "    <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
886                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
887                         out << "      <cond_space id=\"" << cs->condSpaceId << 
888                                 "\" length=\"" << cs->condSet.length() << "\">";
889                         writeKey( cs->baseKey );
890                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
891                                 out << " " << (*csi)->actionId;
892                         out << "</cond_space>\n";
893                 }
894                 out << "    </cond_space_list>\n";
895         }
896 }
897
898 void XMLCodeGen::writeExports()
899 {
900         if ( pd->exportList.length() > 0 ) {
901                 out << "  <exports>\n";
902                 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
903                         out << "    <ex name=\"" << exp->name << "\">";
904                         writeKey( exp->key );
905                         out << "</ex>\n";
906                 }
907                 out << "  </exports>\n";
908         }
909 }
910
911 void XMLCodeGen::writeXML()
912 {
913         /* Open the definition. */
914         out << "<ragel_def name=\"" << fsmName << "\">\n";
915
916         /* Alphabet type. */
917         out << "  <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
918         
919         /* Getkey expression. */
920         if ( pd->getKeyExpr != 0 ) {
921                 out << "  <getkey>";
922                 writeInlineList( pd->getKeyExpr );
923                 out << "</getkey>\n";
924         }
925
926         /* Access expression. */
927         if ( pd->accessExpr != 0 ) {
928                 out << "  <access>";
929                 writeInlineList( pd->accessExpr );
930                 out << "</access>\n";
931         }
932
933         /* PrePush expression. */
934         if ( pd->prePushExpr != 0 ) {
935                 out << "  <prepush>";
936                 writeInlineList( pd->prePushExpr );
937                 out << "</prepush>\n";
938         }
939
940         /* PostPop expression. */
941         if ( pd->postPopExpr != 0 ) {
942                 out << "  <postpop>";
943                 writeInlineList( pd->postPopExpr );
944                 out << "</postpop>\n";
945         }
946
947         /*
948          * Variable expressions.
949          */
950
951         if ( pd->pExpr != 0 ) {
952                 out << "  <p_expr>";
953                 writeInlineList( pd->pExpr );
954                 out << "</p_expr>\n";
955         }
956         
957         if ( pd->peExpr != 0 ) {
958                 out << "  <pe_expr>";
959                 writeInlineList( pd->peExpr );
960                 out << "</pe_expr>\n";
961         }
962
963         if ( pd->eofExpr != 0 ) {
964                 out << "  <eof_expr>";
965                 writeInlineList( pd->eofExpr );
966                 out << "</eof_expr>\n";
967         }
968         
969         if ( pd->csExpr != 0 ) {
970                 out << "  <cs_expr>";
971                 writeInlineList( pd->csExpr );
972                 out << "</cs_expr>\n";
973         }
974         
975         if ( pd->topExpr != 0 ) {
976                 out << "  <top_expr>";
977                 writeInlineList( pd->topExpr );
978                 out << "</top_expr>\n";
979         }
980         
981         if ( pd->stackExpr != 0 ) {
982                 out << "  <stack_expr>";
983                 writeInlineList( pd->stackExpr );
984                 out << "</stack_expr>\n";
985         }
986         
987         if ( pd->actExpr != 0 ) {
988                 out << "  <act_expr>";
989                 writeInlineList( pd->actExpr );
990                 out << "</act_expr>\n";
991         }
992         
993         if ( pd->tokstartExpr != 0 ) {
994                 out << "  <tokstart_expr>";
995                 writeInlineList( pd->tokstartExpr );
996                 out << "</tokstart_expr>\n";
997         }
998         
999         if ( pd->tokendExpr != 0 ) {
1000                 out << "  <tokend_expr>";
1001                 writeInlineList( pd->tokendExpr );
1002                 out << "</tokend_expr>\n";
1003         }
1004         
1005         if ( pd->dataExpr != 0 ) {
1006                 out << "  <data_expr>";
1007                 writeInlineList( pd->dataExpr );
1008                 out << "</data_expr>\n";
1009         }
1010         
1011         writeExports();
1012         
1013         writeMachine();
1014
1015         out <<
1016                 "</ragel_def>\n";
1017 }
1018
1019 void BackendGen::makeExports()
1020 {
1021         for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
1022                 cgd->exportList.append( new Export( exp->name, exp->key ) );
1023 }
1024
1025 void BackendGen::makeAction( Action *action )
1026 {
1027         GenInlineList *genList = new GenInlineList;
1028         makeGenInlineList( genList, action->inlineList );
1029
1030         cgd->newAction( curAction++, action->name, action->loc, genList );
1031 }
1032
1033
1034 void BackendGen::makeActionList()
1035 {
1036         /* Determine which actions to write. */
1037         int nextActionId = 0;
1038         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1039                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
1040                         act->actionId = nextActionId++;
1041         }
1042
1043         /* Write the list. */
1044         cgd->initActionList( nextActionId );
1045         curAction = 0;
1046
1047         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1048                 if ( act->actionId >= 0 )
1049                         makeAction( act );
1050         }
1051 }
1052
1053 void BackendGen::makeActionTableList()
1054 {
1055         /* Must first order the action tables based on their id. */
1056         int numTables = nextActionTableId;
1057         RedActionTable **tables = new RedActionTable*[numTables];
1058         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
1059                 tables[at->id] = at;
1060
1061         cgd->initActionTableList( numTables );
1062         curActionTable = 0;
1063
1064         for ( int t = 0; t < numTables; t++ ) {
1065                 long length = tables[t]->key.length();
1066
1067                 /* Collect the action table. */
1068                 RedAction *redAct = cgd->allActionTables + curActionTable;
1069                 redAct->actListId = curActionTable;
1070                 redAct->key.setAsNew( length );
1071
1072                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
1073                         redAct->key[atel.pos()].key = 0;
1074                         redAct->key[atel.pos()].value = cgd->allActions + 
1075                                         atel->value->actionId;
1076                 }
1077
1078                 /* Insert into the action table map. */
1079                 cgd->redFsm->actionMap.insert( redAct );
1080
1081                 curActionTable += 1;
1082         }
1083
1084         delete[] tables;
1085 }
1086
1087 void BackendGen::makeConditions()
1088 {
1089         if ( condData->condSpaceMap.length() > 0 ) {
1090                 long nextCondSpaceId = 0;
1091                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
1092                         cs->condSpaceId = nextCondSpaceId++;
1093
1094                 long listLength = condData->condSpaceMap.length();
1095                 cgd->initCondSpaceList( listLength );
1096                 curCondSpace = 0;
1097
1098                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
1099                         long id = cs->condSpaceId;
1100                         cgd->newCondSpace( curCondSpace, id, cs->baseKey );
1101                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
1102                                 cgd->condSpaceItem( curCondSpace, (*csi)->actionId );
1103                         curCondSpace += 1;
1104                 }
1105         }
1106 }
1107
1108 bool BackendGen::makeNameInst( std::string &res, NameInst *nameInst )
1109 {
1110         bool written = false;
1111         if ( nameInst->parent != 0 )
1112                 written = makeNameInst( res, nameInst->parent );
1113         
1114         if ( nameInst->name != 0 ) {
1115                 if ( written )
1116                         res += '_';
1117                 res += nameInst->name;
1118                 written = true;
1119         }
1120
1121         return written;
1122 }
1123
1124 void BackendGen::makeEntryPoints()
1125 {
1126         /* List of entry points other than start state. */
1127         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
1128                 if ( pd->lmRequiresErrorState )
1129                         cgd->setForcedErrorState();
1130
1131                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
1132                         /* Get the name instantiation from nameIndex. */
1133                         NameInst *nameInst = pd->nameIndex[en->key];
1134                         std::string name;
1135                         makeNameInst( name, nameInst );
1136                         StateAp *state = en->value;
1137                         cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
1138                 }
1139         }
1140 }
1141
1142 void BackendGen::makeStateActions( StateAp *state )
1143 {
1144         RedActionTable *toStateActions = 0;
1145         if ( state->toStateActionTable.length() > 0 )
1146                 toStateActions = actionTableMap.find( state->toStateActionTable );
1147
1148         RedActionTable *fromStateActions = 0;
1149         if ( state->fromStateActionTable.length() > 0 )
1150                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
1151
1152         /* EOF actions go out here only if the state has no eof target. If it has
1153          * an eof target then an eof transition will be used instead. */
1154         RedActionTable *eofActions = 0;
1155         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
1156                 eofActions = actionTableMap.find( state->eofActionTable );
1157         
1158         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
1159                 long to = -1;
1160                 if ( toStateActions != 0 )
1161                         to = toStateActions->id;
1162
1163                 long from = -1;
1164                 if ( fromStateActions != 0 )
1165                         from = fromStateActions->id;
1166
1167                 long eof = -1;
1168                 if ( eofActions != 0 )
1169                         eof = eofActions->id;
1170
1171                 cgd->setStateActions( curState, to, from, eof );
1172         }
1173 }
1174
1175 void BackendGen::makeEofTrans( StateAp *state )
1176 {
1177         RedActionTable *eofActions = 0;
1178         if ( state->eofActionTable.length() > 0 )
1179                 eofActions = actionTableMap.find( state->eofActionTable );
1180         
1181         /* The EOF trans is used when there is an eof target, otherwise the eof
1182          * action goes into state actions. */
1183         if ( state->eofTarget != 0 ) {
1184                 long targ = state->eofTarget->alg.stateNum;
1185                 long action = -1;
1186                 if ( eofActions != 0 )
1187                         action = eofActions->id;
1188
1189                 cgd->setEofTrans( curState, targ, action );
1190         }
1191 }
1192
1193 void BackendGen::makeStateConditions( StateAp *state )
1194 {
1195         if ( state->stateCondList.length() > 0 ) {
1196                 long length = state->stateCondList.length();
1197                 cgd->initStateCondList( curState, length );
1198                 curStateCond = 0;
1199
1200                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
1201                         cgd->addStateCond( curState, scdi->lowKey, scdi->highKey, 
1202                                         scdi->condSpace->condSpaceId );
1203                 }
1204         }
1205 }
1206
1207 void BackendGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
1208 {
1209         /* First reduce the action. */
1210         RedActionTable *actionTable = 0;
1211         if ( trans->actionTable.length() > 0 )
1212                 actionTable = actionTableMap.find( trans->actionTable );
1213
1214         long targ = -1;
1215         if ( trans->toState != 0 )
1216                 targ = trans->toState->alg.stateNum;
1217
1218         long action = -1;
1219         if ( actionTable != 0 )
1220                 action = actionTable->id;
1221
1222         cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
1223 }
1224
1225 void BackendGen::makeTransList( StateAp *state )
1226 {
1227         TransListVect outList;
1228
1229         /* If there is only are no ranges the task is simple. */
1230         if ( state->outList.length() > 0 ) {
1231                 /* Loop each source range. */
1232                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
1233                         /* Reduce the transition. If it reduced to anything then add it. */
1234                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
1235                 }
1236         }
1237
1238         cgd->initTransList( curState, outList.length() );
1239         curTrans = 0;
1240
1241         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
1242                 makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
1243
1244         cgd->finishTransList( curState );
1245 }
1246
1247
1248 void BackendGen::makeStateList()
1249 {
1250         /* Write the list of states. */
1251         long length = fsm->stateList.length();
1252         cgd->initStateList( length );
1253         curState = 0;
1254         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
1255                 makeStateActions( st );
1256                 makeEofTrans( st );
1257                 makeStateConditions( st );
1258                 makeTransList( st );
1259
1260                 long id = st->alg.stateNum;
1261                 cgd->setId( curState, id );
1262
1263                 if ( st->isFinState() )
1264                         cgd->setFinal( curState );
1265
1266                 curState += 1;
1267         }
1268 }
1269
1270
1271 void BackendGen::makeMachine()
1272 {
1273         cgd->createMachine();
1274
1275         /* Action tables. */
1276         reduceActionTables();
1277
1278         makeActionList();
1279         makeActionTableList();
1280         makeConditions();
1281
1282         /* Start State. */
1283         cgd->setStartState( fsm->startState->alg.stateNum );
1284
1285         /* Error state. */
1286         if ( fsm->errState != 0 )
1287                 cgd->setErrorState( fsm->errState->alg.stateNum );
1288
1289         makeEntryPoints();
1290         makeStateList();
1291
1292         cgd->closeMachine();
1293 }
1294
1295 void BackendGen::close_ragel_def()
1296 {
1297         /* Do this before distributing transitions out to singles and defaults
1298          * makes life easier. */
1299         cgd->redFsm->maxKey = cgd->findMaxKey();
1300
1301         cgd->redFsm->assignActionLocs();
1302
1303         /* Find the first final state (The final state with the lowest id). */
1304         cgd->redFsm->findFirstFinState();
1305
1306         /* Call the user's callback. */
1307         cgd->finishRagelDef();
1308 }
1309
1310
1311 void BackendGen::makeBackend()
1312 {
1313         /* Alphabet type. */
1314         cgd->setAlphType( keyOps->alphType->internalName );
1315         
1316         /* Getkey expression. */
1317         if ( pd->getKeyExpr != 0 ) {
1318                 cgd->getKeyExpr = new GenInlineList;
1319                 makeGenInlineList( cgd->getKeyExpr, pd->getKeyExpr );
1320         }
1321
1322         /* Access expression. */
1323         if ( pd->accessExpr != 0 ) {
1324                 cgd->accessExpr = new GenInlineList;
1325                 makeGenInlineList( cgd->accessExpr, pd->accessExpr );
1326         }
1327
1328         /* PrePush expression. */
1329         if ( pd->prePushExpr != 0 ) {
1330                 cgd->prePushExpr = new GenInlineList;
1331                 makeGenInlineList( cgd->prePushExpr, pd->prePushExpr );
1332         }
1333
1334         /* PostPop expression. */
1335         if ( pd->postPopExpr != 0 ) {
1336                 cgd->postPopExpr = new GenInlineList;
1337                 makeGenInlineList( cgd->postPopExpr, pd->postPopExpr );
1338         }
1339
1340         /*
1341          * Variable expressions.
1342          */
1343
1344         if ( pd->pExpr != 0 ) {
1345                 cgd->pExpr = new GenInlineList;
1346                 makeGenInlineList( cgd->pExpr, pd->pExpr );
1347         }
1348         
1349         if ( pd->peExpr != 0 ) {
1350                 cgd->peExpr = new GenInlineList;
1351                 makeGenInlineList( cgd->peExpr, pd->peExpr );
1352         }
1353
1354         if ( pd->eofExpr != 0 ) {
1355                 cgd->eofExpr = new GenInlineList;
1356                 makeGenInlineList( cgd->eofExpr, pd->eofExpr );
1357         }
1358         
1359         if ( pd->csExpr != 0 ) {
1360                 cgd->csExpr = new GenInlineList;
1361                 makeGenInlineList( cgd->csExpr, pd->csExpr );
1362         }
1363         
1364         if ( pd->topExpr != 0 ) {
1365                 cgd->topExpr = new GenInlineList;
1366                 makeGenInlineList( cgd->topExpr, pd->topExpr );
1367         }
1368         
1369         if ( pd->stackExpr != 0 ) {
1370                 cgd->stackExpr = new GenInlineList;
1371                 makeGenInlineList( cgd->stackExpr, pd->stackExpr );
1372         }
1373         
1374         if ( pd->actExpr != 0 ) {
1375                 cgd->actExpr = new GenInlineList;
1376                 makeGenInlineList( cgd->actExpr, pd->actExpr );
1377         }
1378         
1379         if ( pd->tokstartExpr != 0 ) {
1380                 cgd->tokstartExpr = new GenInlineList;
1381                 makeGenInlineList( cgd->tokstartExpr, pd->tokstartExpr );
1382         }
1383         
1384         if ( pd->tokendExpr != 0 ) {
1385                 cgd->tokendExpr = new GenInlineList;
1386                 makeGenInlineList( cgd->tokendExpr, pd->tokendExpr );
1387         }
1388         
1389         if ( pd->dataExpr != 0 ) {
1390                 cgd->dataExpr = new GenInlineList;
1391                 makeGenInlineList( cgd->dataExpr, pd->dataExpr );
1392         }
1393         
1394         makeExports();
1395         makeMachine();
1396
1397         close_ragel_def();
1398 }
1399
1400 void InputData::writeLanguage( std::ostream &out )
1401 {
1402         out << " lang=\"";
1403         switch ( hostLang->lang ) {
1404                 case HostLang::C:    out << "C"; break;
1405                 case HostLang::D:    out << "D"; break;
1406                 case HostLang::Java: out << "Java"; break;
1407                 case HostLang::Ruby: out << "Ruby"; break;
1408                 case HostLang::CSharp: out << "C#"; break;
1409         }
1410         out << "\"";
1411 }
1412
1413 void InputData::writeXML( std::ostream &out )
1414 {
1415         out << "<ragel version=\"" VERSION "\" filename=\"" << inputFileName << "\"";
1416         writeLanguage( out );
1417         out << ">\n";
1418
1419         for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) {
1420                 ParseData *pd = parser->value->pd;
1421                 if ( pd->instanceList.length() > 0 )
1422                         pd->generateXML( *outStream );
1423         }
1424
1425         out << "</ragel>\n";
1426 }