More work on the direct connection between frontend and backend. Now appears to
[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 "xmlparse.h"
26 #include "parsedata.h"
27 #include "fsmgraph.h"
28 #include "gendata.h"
29 #include <string.h>
30
31 using namespace std;
32
33 GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm, XmlParser &xmlParser )
34 :
35         fsmName(fsmName),
36         pd(pd),
37         fsm(fsm),
38         xmlParser(xmlParser),
39         nextActionTableId(0)
40 {
41 }
42
43 void GenBase::appendTrans( TransListVect &outList, Key lowKey, 
44                 Key highKey, TransAp *trans )
45 {
46         if ( trans->toState != 0 || trans->actionTable.length() > 0 )
47                 outList.append( TransEl( lowKey, highKey, trans ) );
48 }
49
50 void GenBase::reduceActionTables()
51 {
52         /* Reduce the actions tables to a set. */
53         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
54                 RedActionTable *actionTable = 0;
55
56                 /* Reduce To State Actions. */
57                 if ( st->toStateActionTable.length() > 0 ) {
58                         if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
59                                 actionTable->id = nextActionTableId++;
60                 }
61
62                 /* Reduce From State Actions. */
63                 if ( st->fromStateActionTable.length() > 0 ) {
64                         if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
65                                 actionTable->id = nextActionTableId++;
66                 }
67
68                 /* Reduce EOF actions. */
69                 if ( st->eofActionTable.length() > 0 ) {
70                         if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
71                                 actionTable->id = nextActionTableId++;
72                 }
73
74                 /* Loop the transitions and reduce their actions. */
75                 for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
76                         if ( trans->actionTable.length() > 0 ) {
77                                 if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
78                                         actionTable->id = nextActionTableId++;
79                         }
80                 }
81         }
82 }
83
84 XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, 
85                 std::ostream &out, XmlParser &xmlParser )
86 :
87         GenBase(fsmName, pd, fsm, xmlParser),
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, XmlParser &xmlParser )
452 :
453         GenBase(fsmName, pd, fsm, xmlParser)
454 {
455 }
456
457
458 void BackendGen::makeText( GenInlineList *outList, InlineItem *item )
459 {
460         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text );
461         inlineItem->data = item->data;
462
463         outList->append( inlineItem );
464 }
465
466 void BackendGen::makeTargetItem( GenInlineList *outList, long entryId, GenInlineItem::Type type )
467 {
468         long targetState;
469         if ( pd->generatingSectionSubset )
470                 targetState = -1;
471         else {
472                 EntryMapEl *targ = fsm->entryPoints.find( entryId );
473                 targetState = targ->value->alg.stateNum;
474         }
475
476         /* Make the item. */
477         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
478         inlineItem->targId = targetState;
479         outList->append( inlineItem );
480 }
481
482 /* Make a sublist item with a given type. */
483 void BackendGen::makeSubList( GenInlineList *outList, 
484                 InlineList *inlineList, GenInlineItem::Type type )
485 {
486         /* Fill the sub list. */
487         GenInlineList *subList = new GenInlineList;
488         makeGenInlineList( subList, inlineList );
489
490         /* Make the item. */
491         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
492         inlineItem->children = subList;
493         outList->append( inlineItem );
494 }
495
496 void BackendGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
497 {
498         makeSetTokend( outList, 1 );
499
500         if ( item->longestMatchPart->action != 0 ) {
501                 makeSubList( outList, 
502                                 item->longestMatchPart->action->inlineList, 
503                                 GenInlineItem::SubAction );
504         }
505 }
506
507 void BackendGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
508 {
509         makeSetTokend( outList, 0 );
510         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
511
512         if ( item->longestMatchPart->action != 0 ) {
513                 makeSubList( outList, 
514                         item->longestMatchPart->action->inlineList,
515                         GenInlineItem::SubAction );
516         }
517 }
518
519 void BackendGen::makeExecGetTokend( GenInlineList *outList )
520 {
521         /* Make the Exec item. */
522         GenInlineItem *execItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
523         execItem->children = new GenInlineList;
524
525         /* Make the GetTokEnd */
526         GenInlineItem *getTokend = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
527         execItem->children->append( getTokend );
528
529         outList->append( execItem );
530 }
531
532 void BackendGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
533 {
534         /* Jump to the tokend. */
535         makeExecGetTokend( outList );
536
537         if ( item->longestMatchPart->action != 0 ) {
538                 makeSubList( outList,
539                         item->longestMatchPart->action->inlineList,
540                         GenInlineItem::SubAction );
541         }
542 }
543
544 void BackendGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
545 {
546         GenInlineItem *lmSwitch = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
547         GenInlineList *lmList = lmSwitch->children = new GenInlineList;
548         LongestMatch *longestMatch = item->longestMatch;
549
550         /* We can't put the <exec> here because we may need to handle the error
551          * case and in that case p should not be changed. Instead use a default
552          * label in the switch to adjust p when user actions are not set. An id of
553          * -1 indicates the default. */
554
555         if ( longestMatch->lmSwitchHandlesError ) {
556                 /* If the switch handles error then we should have also forced the
557                  * error state. */
558                 assert( fsm->errState != 0 );
559
560                 GenInlineItem *errCase = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
561                 errCase->lmId = 0;
562                 errCase->children = new GenInlineList;
563
564                 /* Make the item. */
565                 GenInlineItem *gotoItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
566                 gotoItem->targId = fsm->errState->alg.stateNum;
567                 errCase->children->append( gotoItem );
568
569                 lmList->append( errCase );
570         }
571         
572         bool needDefault = false;
573         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
574                 if ( lmi->inLmSelect ) {
575                         if ( lmi->action == 0 )
576                                 needDefault = true;
577                         else {
578                                 /* Open the action. Write it with the context that sets up _p 
579                                  * when doing control flow changes from inside the machine. */
580                                 GenInlineItem *lmCase = new GenInlineItem( InputLoc(), 
581                                                 GenInlineItem::SubAction );
582                                 lmCase->lmId = lmi->longestMatchId;
583                                 lmCase->children = new GenInlineList;
584
585                                 makeExecGetTokend( lmCase->children );
586                                 makeGenInlineList( lmCase->children, lmi->action->inlineList );
587
588                                 lmList->append( lmCase );
589                         }
590                 }
591         }
592
593         if ( needDefault ) {
594                 GenInlineItem *defCase = new GenInlineItem( InputLoc(), 
595                                 GenInlineItem::SubAction );
596                 defCase->lmId = -1;
597                 defCase->children = new GenInlineList;
598
599                 makeExecGetTokend( defCase->children );
600
601                 lmList->append( defCase );
602         }
603
604         outList->append( lmSwitch );
605 }
606
607 void BackendGen::makeSetTokend( GenInlineList *outList, long offset )
608 {
609         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
610         inlineItem->offset = offset;
611         outList->append( inlineItem );
612 }
613
614 void BackendGen::makeSetAct( GenInlineList *outList, long lmId )
615 {
616         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
617         inlineItem->lmId = lmId;
618         outList->append( inlineItem );
619 }
620
621 void BackendGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
622 {
623         for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
624                 switch ( item->type ) {
625                 case InlineItem::Text:
626                         makeText( outList, item );
627                         break;
628                 case InlineItem::Goto:
629                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Goto );
630                         break;
631                 case InlineItem::GotoExpr:
632                         makeSubList( outList, item->children, GenInlineItem::GotoExpr );
633                         break;
634                 case InlineItem::Call:
635                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Call );
636                         break;
637                 case InlineItem::CallExpr:
638                         makeSubList( outList, item->children, GenInlineItem::CallExpr );
639                         break;
640                 case InlineItem::Next:
641                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Next );
642                         break;
643                 case InlineItem::NextExpr:
644                         makeSubList( outList, item->children, GenInlineItem::NextExpr );
645                         break;
646                 case InlineItem::Break:
647                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Break ) );
648                         break;
649                 case InlineItem::Ret: 
650                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret ) );
651                         break;
652                 case InlineItem::PChar:
653                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar ) );
654                         break;
655                 case InlineItem::Char: 
656                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Char ) );
657                         break;
658                 case InlineItem::Curs: 
659                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs ) );
660                         break;
661                 case InlineItem::Targs: 
662                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs ) );
663                         break;
664                 case InlineItem::Entry:
665                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Entry );
666                         break;
667
668                 case InlineItem::Hold:
669                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
670                         break;
671                 case InlineItem::Exec:
672                         makeSubList( outList, item->children, GenInlineItem::Exec );
673                         break;
674
675                 case InlineItem::LmSetActId:
676                         makeSetAct( outList, item->longestMatchPart->longestMatchId );
677                         break;
678                 case InlineItem::LmSetTokEnd:
679                         makeSetTokend( outList, 1 );
680                         break;
681
682                 case InlineItem::LmOnLast:
683                         makeLmOnLast( outList, item );
684                         break;
685                 case InlineItem::LmOnNext:
686                         makeLmOnNext( outList, item );
687                         break;
688                 case InlineItem::LmOnLagBehind:
689                         makeLmOnLagBehind( outList, item );
690                         break;
691                 case InlineItem::LmSwitch: 
692                         makeLmSwitch( outList, item );
693                         break;
694
695                 case InlineItem::LmInitAct:
696                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ) );
697                         break;
698                 case InlineItem::LmInitTokStart:
699                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ) );
700                         break;
701                 case InlineItem::LmSetTokStart:
702                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ) );
703                         xmlParser.cgd->hasLongestMatch = true;
704                         break;
705                 }
706         }
707 }
708
709
710 void XMLCodeGen::writeAction( Action *action )
711 {
712         out << "      <action id=\"" << action->actionId << "\"";
713         if ( action->name != 0 ) 
714                 out << " name=\"" << action->name << "\"";
715         out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
716         writeInlineList( action->inlineList );
717         out << "</action>\n";
718 }
719
720 void xmlEscapeHost( std::ostream &out, char *data, long len )
721 {
722         char *end = data + len;
723         while ( data != end ) {
724                 switch ( *data ) {
725                 case '<': out << "&lt;"; break;
726                 case '>': out << "&gt;"; break;
727                 case '&': out << "&amp;"; break;
728                 default: out << *data; break;
729                 }
730                 data += 1;
731         }
732 }
733
734 void XMLCodeGen::writeStateActions( StateAp *state )
735 {
736         RedActionTable *toStateActions = 0;
737         if ( state->toStateActionTable.length() > 0 )
738                 toStateActions = actionTableMap.find( state->toStateActionTable );
739
740         RedActionTable *fromStateActions = 0;
741         if ( state->fromStateActionTable.length() > 0 )
742                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
743
744         /* EOF actions go out here only if the state has no eof target. If it has
745          * an eof target then an eof transition will be used instead. */
746         RedActionTable *eofActions = 0;
747         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
748                 eofActions = actionTableMap.find( state->eofActionTable );
749         
750         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
751                 out << "      <state_actions>";
752                 if ( toStateActions != 0 )
753                         out << toStateActions->id;
754                 else
755                         out << "x";
756
757                 if ( fromStateActions != 0 )
758                         out << " " << fromStateActions->id;
759                 else
760                         out << " x";
761
762                 if ( eofActions != 0 )
763                         out << " " << eofActions->id;
764                 else
765                         out << " x";
766
767                 out << "</state_actions>\n";
768         }
769 }
770
771 void XMLCodeGen::writeStateConditions( StateAp *state )
772 {
773         if ( state->stateCondList.length() > 0 ) {
774                 out << "      <cond_list length=\"" << state->stateCondList.length() << "\">\n";
775                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
776                         out << "        <c>";
777                         writeKey( scdi->lowKey );
778                         out << " ";
779                         writeKey( scdi->highKey );
780                         out << " ";
781                         out << scdi->condSpace->condSpaceId;
782                         out << "</c>\n";
783                 }
784                 out << "      </cond_list>\n";
785         }
786 }
787
788 void XMLCodeGen::writeStateList()
789 {
790         /* Write the list of states. */
791         out << "    <state_list length=\"" << fsm->stateList.length() << "\">\n";
792         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
793                 out << "      <state id=\"" << st->alg.stateNum << "\"";
794                 if ( st->isFinState() )
795                         out << " final=\"t\"";
796                 out << ">\n";
797
798                 writeStateActions( st );
799                 writeEofTrans( st );
800                 writeStateConditions( st );
801                 writeTransList( st );
802
803                 out << "      </state>\n";
804
805                 if ( !st.last() )
806                         out << "\n";
807         }
808         out << "    </state_list>\n";
809 }
810
811 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
812 {
813         bool written = false;
814         if ( nameInst->parent != 0 )
815                 written = writeNameInst( nameInst->parent );
816         
817         if ( nameInst->name != 0 ) {
818                 if ( written )
819                         out << '_';
820                 out << nameInst->name;
821                 written = true;
822         }
823
824         return written;
825 }
826
827 void XMLCodeGen::writeEntryPoints()
828 {
829         /* List of entry points other than start state. */
830         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
831                 out << "    <entry_points";
832                 if ( pd->lmRequiresErrorState )
833                         out << " error=\"t\"";
834                 out << ">\n";
835                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
836                         /* Get the name instantiation from nameIndex. */
837                         NameInst *nameInst = pd->nameIndex[en->key];
838                         StateAp *state = en->value;
839                         out << "      <entry name=\"";
840                         writeNameInst( nameInst );
841                         out << "\">" << state->alg.stateNum << "</entry>\n";
842                 }
843                 out << "    </entry_points>\n";
844         }
845 }
846
847 void XMLCodeGen::writeMachine()
848 {
849         /* Open the machine. */
850         out << "  <machine>\n"; 
851         
852         /* Action tables. */
853         reduceActionTables();
854
855         writeActionList();
856         writeActionTableList();
857         writeConditions();
858
859         /* Start state. */
860         out << "    <start_state>" << fsm->startState->alg.stateNum << 
861                         "</start_state>\n";
862         
863         /* Error state. */
864         if ( fsm->errState != 0 ) {
865                 out << "    <error_state>" << fsm->errState->alg.stateNum << 
866                         "</error_state>\n";
867         }
868
869         writeEntryPoints();
870         writeStateList();
871
872         out << "  </machine>\n";
873 }
874
875
876 void XMLCodeGen::writeConditions()
877 {
878         if ( condData->condSpaceMap.length() > 0 ) {
879                 long nextCondSpaceId = 0;
880                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
881                         cs->condSpaceId = nextCondSpaceId++;
882
883                 out << "    <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
884                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
885                         out << "      <cond_space id=\"" << cs->condSpaceId << 
886                                 "\" length=\"" << cs->condSet.length() << "\">";
887                         writeKey( cs->baseKey );
888                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
889                                 out << " " << (*csi)->actionId;
890                         out << "</cond_space>\n";
891                 }
892                 out << "    </cond_space_list>\n";
893         }
894 }
895
896 void XMLCodeGen::writeExports()
897 {
898         if ( pd->exportList.length() > 0 ) {
899                 out << "  <exports>\n";
900                 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
901                         out << "    <ex name=\"" << exp->name << "\">";
902                         writeKey( exp->key );
903                         out << "</ex>\n";
904                 }
905                 out << "  </exports>\n";
906         }
907 }
908
909 void XMLCodeGen::writeXML()
910 {
911         /* Open the definition. */
912         out << "<ragel_def name=\"" << fsmName << "\">\n";
913
914         /* Alphabet type. */
915         out << "  <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
916         
917         /* Getkey expression. */
918         if ( pd->getKeyExpr != 0 ) {
919                 out << "  <getkey>";
920                 writeInlineList( pd->getKeyExpr );
921                 out << "</getkey>\n";
922         }
923
924         /* Access expression. */
925         if ( pd->accessExpr != 0 ) {
926                 out << "  <access>";
927                 writeInlineList( pd->accessExpr );
928                 out << "</access>\n";
929         }
930
931         /* PrePush expression. */
932         if ( pd->prePushExpr != 0 ) {
933                 out << "  <prepush>";
934                 writeInlineList( pd->prePushExpr );
935                 out << "</prepush>\n";
936         }
937
938         /* PostPop expression. */
939         if ( pd->postPopExpr != 0 ) {
940                 out << "  <postpop>";
941                 writeInlineList( pd->postPopExpr );
942                 out << "</postpop>\n";
943         }
944
945         /*
946          * Variable expressions.
947          */
948
949         if ( pd->pExpr != 0 ) {
950                 out << "  <p_expr>";
951                 writeInlineList( pd->pExpr );
952                 out << "</p_expr>\n";
953         }
954         
955         if ( pd->peExpr != 0 ) {
956                 out << "  <pe_expr>";
957                 writeInlineList( pd->peExpr );
958                 out << "</pe_expr>\n";
959         }
960
961         if ( pd->eofExpr != 0 ) {
962                 out << "  <eof_expr>";
963                 writeInlineList( pd->eofExpr );
964                 out << "</eof_expr>\n";
965         }
966         
967         if ( pd->csExpr != 0 ) {
968                 out << "  <cs_expr>";
969                 writeInlineList( pd->csExpr );
970                 out << "</cs_expr>\n";
971         }
972         
973         if ( pd->topExpr != 0 ) {
974                 out << "  <top_expr>";
975                 writeInlineList( pd->topExpr );
976                 out << "</top_expr>\n";
977         }
978         
979         if ( pd->stackExpr != 0 ) {
980                 out << "  <stack_expr>";
981                 writeInlineList( pd->stackExpr );
982                 out << "</stack_expr>\n";
983         }
984         
985         if ( pd->actExpr != 0 ) {
986                 out << "  <act_expr>";
987                 writeInlineList( pd->actExpr );
988                 out << "</act_expr>\n";
989         }
990         
991         if ( pd->tokstartExpr != 0 ) {
992                 out << "  <tokstart_expr>";
993                 writeInlineList( pd->tokstartExpr );
994                 out << "</tokstart_expr>\n";
995         }
996         
997         if ( pd->tokendExpr != 0 ) {
998                 out << "  <tokend_expr>";
999                 writeInlineList( pd->tokendExpr );
1000                 out << "</tokend_expr>\n";
1001         }
1002         
1003         if ( pd->dataExpr != 0 ) {
1004                 out << "  <data_expr>";
1005                 writeInlineList( pd->dataExpr );
1006                 out << "</data_expr>\n";
1007         }
1008         
1009         writeExports();
1010         
1011         writeMachine();
1012
1013         out <<
1014                 "</ragel_def>\n";
1015 }
1016
1017 void BackendGen::makeExports()
1018 {
1019         for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
1020                 xmlParser.cgd->exportList.append( new Export( exp->name, exp->key ) );
1021 }
1022
1023 void BackendGen::makeAction( Action *action )
1024 {
1025         GenInlineList *genList = new GenInlineList;
1026         makeGenInlineList( genList, action->inlineList );
1027
1028         xmlParser.cgd->newAction( xmlParser.curAction++, action->name, 
1029                         action->loc.line, action->loc.col, genList );
1030 }
1031
1032
1033 void BackendGen::makeActionList()
1034 {
1035         /* Determine which actions to write. */
1036         int nextActionId = 0;
1037         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1038                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
1039                         act->actionId = nextActionId++;
1040         }
1041
1042         /* Write the list. */
1043         xmlParser.cgd->initActionList( nextActionId );
1044         xmlParser.curAction = 0;
1045
1046         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1047                 if ( act->actionId >= 0 )
1048                         makeAction( act );
1049         }
1050 }
1051
1052 void BackendGen::makeActionTableList()
1053 {
1054         /* Must first order the action tables based on their id. */
1055         int numTables = nextActionTableId;
1056         RedActionTable **tables = new RedActionTable*[numTables];
1057         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
1058                 tables[at->id] = at;
1059
1060         xmlParser.cgd->initActionTableList( numTables );
1061         xmlParser.curActionTable = 0;
1062
1063         for ( int t = 0; t < numTables; t++ ) {
1064                 long length = tables[t]->key.length();
1065
1066                 /* Collect the action table. */
1067                 RedAction *redAct = xmlParser.cgd->allActionTables + xmlParser.curActionTable;
1068                 redAct->actListId = xmlParser.curActionTable;
1069                 redAct->key.setAsNew( length );
1070
1071                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
1072                         redAct->key[atel.pos()].key = 0;
1073                         redAct->key[atel.pos()].value = xmlParser.cgd->allActions + 
1074                                         atel->value->actionId;
1075                 }
1076
1077                 /* Insert into the action table map. */
1078                 xmlParser.cgd->redFsm->actionMap.insert( redAct );
1079
1080                 xmlParser.curActionTable += 1;
1081         }
1082
1083         delete[] tables;
1084 }
1085
1086 void BackendGen::makeConditions()
1087 {
1088         if ( condData->condSpaceMap.length() > 0 ) {
1089                 long nextCondSpaceId = 0;
1090                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
1091                         cs->condSpaceId = nextCondSpaceId++;
1092
1093                 long listLength = condData->condSpaceMap.length();
1094                 xmlParser.cgd->initCondSpaceList( listLength );
1095                 xmlParser.curCondSpace = 0;
1096
1097                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
1098                         long id = cs->condSpaceId;
1099                         xmlParser.cgd->newCondSpace( xmlParser.curCondSpace, id, cs->baseKey );
1100                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
1101                                 xmlParser.cgd->condSpaceItem( xmlParser.curCondSpace, (*csi)->actionId );
1102                         xmlParser.curCondSpace += 1;
1103                 }
1104         }
1105 }
1106
1107 bool BackendGen::makeNameInst( std::string &res, NameInst *nameInst )
1108 {
1109         bool written = false;
1110         if ( nameInst->parent != 0 )
1111                 written = makeNameInst( res, nameInst->parent );
1112         
1113         if ( nameInst->name != 0 ) {
1114                 if ( written )
1115                         res += '_';
1116                 res += nameInst->name;
1117                 written = true;
1118         }
1119
1120         return written;
1121 }
1122
1123 void BackendGen::makeEntryPoints()
1124 {
1125         /* List of entry points other than start state. */
1126         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
1127                 if ( pd->lmRequiresErrorState )
1128                         xmlParser.cgd->setForcedErrorState();
1129
1130                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
1131                         /* Get the name instantiation from nameIndex. */
1132                         NameInst *nameInst = pd->nameIndex[en->key];
1133                         std::string name;
1134                         makeNameInst( name, nameInst );
1135                         StateAp *state = en->value;
1136                         xmlParser.cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
1137                 }
1138         }
1139 }
1140
1141 void BackendGen::makeStateActions( StateAp *state )
1142 {
1143         RedActionTable *toStateActions = 0;
1144         if ( state->toStateActionTable.length() > 0 )
1145                 toStateActions = actionTableMap.find( state->toStateActionTable );
1146
1147         RedActionTable *fromStateActions = 0;
1148         if ( state->fromStateActionTable.length() > 0 )
1149                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
1150
1151         /* EOF actions go out here only if the state has no eof target. If it has
1152          * an eof target then an eof transition will be used instead. */
1153         RedActionTable *eofActions = 0;
1154         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
1155                 eofActions = actionTableMap.find( state->eofActionTable );
1156         
1157         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
1158                 long to = -1;
1159                 if ( toStateActions != 0 )
1160                         to = toStateActions->id;
1161
1162                 long from = -1;
1163                 if ( fromStateActions != 0 )
1164                         from = fromStateActions->id;
1165
1166                 long eof = -1;
1167                 if ( eofActions != 0 )
1168                         eof = eofActions->id;
1169
1170                 xmlParser.cgd->setStateActions( xmlParser.curState, to, from, eof );
1171         }
1172 }
1173
1174 void BackendGen::makeEofTrans( StateAp *state )
1175 {
1176         RedActionTable *eofActions = 0;
1177         if ( state->eofActionTable.length() > 0 )
1178                 eofActions = actionTableMap.find( state->eofActionTable );
1179         
1180         /* The EOF trans is used when there is an eof target, otherwise the eof
1181          * action goes into state actions. */
1182         if ( state->eofTarget != 0 ) {
1183                 long targ = state->eofTarget->alg.stateNum;
1184                 long action = -1;
1185                 if ( eofActions != 0 )
1186                         action = eofActions->id;
1187
1188                 xmlParser.cgd->setEofTrans( xmlParser.curState, targ, action );
1189         }
1190 }
1191
1192 void BackendGen::makeStateConditions( StateAp *state )
1193 {
1194         if ( state->stateCondList.length() > 0 ) {
1195                 long length = state->stateCondList.length();
1196                 xmlParser.cgd->initStateCondList( xmlParser.curState, length );
1197                 xmlParser.curStateCond = 0;
1198
1199                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
1200                         xmlParser.cgd->addStateCond( xmlParser.curState, scdi->lowKey, scdi->highKey, 
1201                                         scdi->condSpace->condSpaceId );
1202                 }
1203         }
1204 }
1205
1206 void BackendGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
1207 {
1208         /* First reduce the action. */
1209         RedActionTable *actionTable = 0;
1210         if ( trans->actionTable.length() > 0 )
1211                 actionTable = actionTableMap.find( trans->actionTable );
1212
1213         long targ = -1;
1214         if ( trans->toState != 0 )
1215                 targ = trans->toState->alg.stateNum;
1216
1217         long action = -1;
1218         if ( actionTable != 0 )
1219                 action = actionTable->id;
1220
1221         xmlParser.cgd->newTrans( xmlParser.curState, xmlParser.curTrans++, lowKey, highKey, targ, action );
1222 }
1223
1224 void BackendGen::makeTransList( StateAp *state )
1225 {
1226         TransListVect outList;
1227
1228         /* If there is only are no ranges the task is simple. */
1229         if ( state->outList.length() > 0 ) {
1230                 /* Loop each source range. */
1231                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
1232                         /* Reduce the transition. If it reduced to anything then add it. */
1233                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
1234                 }
1235         }
1236
1237         xmlParser.cgd->initTransList( xmlParser.curState, outList.length() );
1238         xmlParser.curTrans = 0;
1239
1240         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
1241                 makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
1242
1243         xmlParser.cgd->finishTransList( xmlParser.curState );
1244 }
1245
1246
1247 void BackendGen::makeStateList()
1248 {
1249         /* Write the list of states. */
1250         long length = fsm->stateList.length();
1251         xmlParser.cgd->initStateList( length );
1252         xmlParser.curState = 0;
1253         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
1254                 makeStateActions( st );
1255                 makeEofTrans( st );
1256                 makeStateConditions( st );
1257                 makeTransList( st );
1258
1259                 long id = st->alg.stateNum;
1260                 xmlParser.cgd->setId( xmlParser.curState, id );
1261
1262                 if ( st->isFinState() )
1263                         xmlParser.cgd->setFinal( xmlParser.curState );
1264
1265                 xmlParser.curState += 1;
1266         }
1267 }
1268
1269
1270 void BackendGen::makeMachine()
1271 {
1272         xmlParser.cgd->createMachine();
1273
1274         /* Action tables. */
1275         reduceActionTables();
1276
1277         makeActionList();
1278         makeActionTableList();
1279         makeConditions();
1280
1281         /* Start State. */
1282         xmlParser.cgd->setStartState( fsm->startState->alg.stateNum );
1283
1284         /* Error state. */
1285         if ( fsm->errState != 0 )
1286                 xmlParser.cgd->setErrorState( fsm->errState->alg.stateNum );
1287
1288         makeEntryPoints();
1289         makeStateList();
1290
1291         xmlParser.cgd->closeMachine();
1292 }
1293
1294 void BackendGen::makeBackend()
1295 {
1296         /* Open the definition. */
1297         xmlParser.open_ragel_def( fsmName );
1298
1299         /* Alphabet type. */
1300         xmlParser.cgd->setAlphType( keyOps->alphType->internalName );
1301         
1302         /* Getkey expression. */
1303         if ( pd->getKeyExpr != 0 ) {
1304                 xmlParser.cgd->getKeyExpr = new GenInlineList;
1305                 makeGenInlineList( xmlParser.cgd->getKeyExpr, pd->getKeyExpr );
1306         }
1307
1308         /* Access expression. */
1309         if ( pd->accessExpr != 0 ) {
1310                 xmlParser.cgd->accessExpr = new GenInlineList;
1311                 makeGenInlineList( xmlParser.cgd->accessExpr, pd->accessExpr );
1312         }
1313
1314         /* PrePush expression. */
1315         if ( pd->prePushExpr != 0 ) {
1316                 xmlParser.cgd->prePushExpr = new GenInlineList;
1317                 makeGenInlineList( xmlParser.cgd->prePushExpr, pd->prePushExpr );
1318         }
1319
1320         /* PostPop expression. */
1321         if ( pd->postPopExpr != 0 ) {
1322                 xmlParser.cgd->postPopExpr = new GenInlineList;
1323                 makeGenInlineList( xmlParser.cgd->postPopExpr, pd->postPopExpr );
1324         }
1325
1326         /*
1327          * Variable expressions.
1328          */
1329
1330         if ( pd->pExpr != 0 ) {
1331                 xmlParser.cgd->pExpr = new GenInlineList;
1332                 makeGenInlineList( xmlParser.cgd->pExpr, pd->pExpr );
1333         }
1334         
1335         if ( pd->peExpr != 0 ) {
1336                 xmlParser.cgd->peExpr = new GenInlineList;
1337                 makeGenInlineList( xmlParser.cgd->peExpr, pd->peExpr );
1338         }
1339
1340         if ( pd->eofExpr != 0 ) {
1341                 xmlParser.cgd->eofExpr = new GenInlineList;
1342                 makeGenInlineList( xmlParser.cgd->eofExpr, pd->eofExpr );
1343         }
1344         
1345         if ( pd->csExpr != 0 ) {
1346                 xmlParser.cgd->csExpr = new GenInlineList;
1347                 makeGenInlineList( xmlParser.cgd->csExpr, pd->csExpr );
1348         }
1349         
1350         if ( pd->topExpr != 0 ) {
1351                 xmlParser.cgd->topExpr = new GenInlineList;
1352                 makeGenInlineList( xmlParser.cgd->topExpr, pd->topExpr );
1353         }
1354         
1355         if ( pd->stackExpr != 0 ) {
1356                 xmlParser.cgd->stackExpr = new GenInlineList;
1357                 makeGenInlineList( xmlParser.cgd->stackExpr, pd->stackExpr );
1358         }
1359         
1360         if ( pd->actExpr != 0 ) {
1361                 xmlParser.cgd->actExpr = new GenInlineList;
1362                 makeGenInlineList( xmlParser.cgd->actExpr, pd->actExpr );
1363         }
1364         
1365         if ( pd->tokstartExpr != 0 ) {
1366                 xmlParser.cgd->tokstartExpr = new GenInlineList;
1367                 makeGenInlineList( xmlParser.cgd->tokstartExpr, pd->tokstartExpr );
1368         }
1369         
1370         if ( pd->tokendExpr != 0 ) {
1371                 xmlParser.cgd->tokendExpr = new GenInlineList;
1372                 makeGenInlineList( xmlParser.cgd->tokendExpr, pd->tokendExpr );
1373         }
1374         
1375         if ( pd->dataExpr != 0 ) {
1376                 xmlParser.cgd->dataExpr = new GenInlineList;
1377                 makeGenInlineList( xmlParser.cgd->dataExpr, pd->dataExpr );
1378         }
1379         
1380         makeExports();
1381         makeMachine();
1382
1383         xmlParser.close_ragel_def();
1384 }
1385
1386