Some more refactoring following the elimination of the intermediate file. Don't
[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 "inputdata.h"
30 #include <string.h>
31
32 using namespace std;
33
34 GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm, InputData &inputData )
35 :
36         fsmName(fsmName),
37         pd(pd),
38         fsm(fsm),
39         inputData(inputData),
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, 
86                 std::ostream &out, InputData &inputData )
87 :
88         GenBase(fsmName, pd, fsm, inputData),
89         out(out)
90 {
91 }
92
93
94 void XMLCodeGen::writeActionList()
95 {
96         /* Determine which actions to write. */
97         int nextActionId = 0;
98         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
99                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
100                         act->actionId = nextActionId++;
101         }
102
103         /* Write the list. */
104         out << "    <action_list length=\"" << nextActionId << "\">\n";
105         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
106                 if ( act->actionId >= 0 )
107                         writeAction( act );
108         }
109         out << "    </action_list>\n";
110 }
111
112 void XMLCodeGen::writeActionTableList()
113 {
114         /* Must first order the action tables based on their id. */
115         int numTables = nextActionTableId;
116         RedActionTable **tables = new RedActionTable*[numTables];
117         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
118                 tables[at->id] = at;
119
120         out << "    <action_table_list length=\"" << numTables << "\">\n";
121         for ( int t = 0; t < numTables; t++ ) {
122                 out << "      <action_table id=\"" << t << "\" length=\"" << 
123                                 tables[t]->key.length() << "\">";
124                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
125                         out << atel->value->actionId;
126                         if ( ! atel.last() )
127                                 out << " ";
128                 }
129                 out << "</action_table>\n";
130         }
131         out << "    </action_table_list>\n";
132
133         delete[] tables;
134 }
135
136 void XMLCodeGen::writeKey( Key key )
137 {
138         if ( keyOps->isSigned )
139                 out << key.getVal();
140         else
141                 out << (unsigned long) key.getVal();
142 }
143
144 void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
145 {
146         /* First reduce the action. */
147         RedActionTable *actionTable = 0;
148         if ( trans->actionTable.length() > 0 )
149                 actionTable = actionTableMap.find( trans->actionTable );
150
151         /* Write the transition. */
152         out << "        <t>";
153         writeKey( lowKey );
154         out << " ";
155         writeKey( highKey );
156
157         if ( trans->toState != 0 )
158                 out << " " << trans->toState->alg.stateNum;
159         else
160                 out << " x";
161
162         if ( actionTable != 0 )
163                 out << " " << actionTable->id;
164         else
165                 out << " x";
166         out << "</t>\n";
167 }
168
169 void XMLCodeGen::writeTransList( StateAp *state )
170 {
171         TransListVect outList;
172
173         /* If there is only are no ranges the task is simple. */
174         if ( state->outList.length() > 0 ) {
175                 /* Loop each source range. */
176                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
177                         /* Reduce the transition. If it reduced to anything then add it. */
178                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
179                 }
180         }
181
182         out << "      <trans_list length=\"" << outList.length() << "\">\n";
183         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
184                 writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
185         out << "      </trans_list>\n";
186 }
187
188 void XMLCodeGen::writeEofTrans( StateAp *state )
189 {
190         RedActionTable *eofActions = 0;
191         if ( state->eofActionTable.length() > 0 )
192                 eofActions = actionTableMap.find( state->eofActionTable );
193         
194         /* The <eof_t> is used when there is an eof target, otherwise the eof
195          * action goes into state actions. */
196         if ( state->eofTarget != 0 ) {
197                 out << "      <eof_t>" << state->eofTarget->alg.stateNum;
198
199                 if ( eofActions != 0 )
200                         out << " " << eofActions->id;
201                 else
202                         out << " x"; 
203
204                 out << "</eof_t>" << endl;
205         }
206 }
207
208 void XMLCodeGen::writeText( InlineItem *item )
209 {
210         if ( item->prev == 0 || item->prev->type != InlineItem::Text )
211                 out << "<text>";
212         xmlEscapeHost( out, item->data, strlen(item->data) );
213         if ( item->next == 0 || item->next->type != InlineItem::Text )
214                 out << "</text>";
215 }
216
217 void XMLCodeGen::writeGoto( InlineItem *item )
218 {
219         if ( pd->generatingSectionSubset )
220                 out << "<goto>-1</goto>";
221         else {
222                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
223                 out << "<goto>" << targ->value->alg.stateNum << "</goto>";
224         }
225 }
226
227 void XMLCodeGen::writeCall( InlineItem *item )
228 {
229         if ( pd->generatingSectionSubset )
230                 out << "<call>-1</call>";
231         else {
232                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
233                 out << "<call>" << targ->value->alg.stateNum << "</call>";
234         }
235 }
236
237 void XMLCodeGen::writeNext( InlineItem *item )
238 {
239         if ( pd->generatingSectionSubset )
240                 out << "<next>-1</next>";
241         else {
242                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
243                 out << "<next>" << targ->value->alg.stateNum << "</next>";
244         }
245 }
246
247 void XMLCodeGen::writeGotoExpr( InlineItem *item )
248 {
249         out << "<goto_expr>";
250         writeInlineList( item->children );
251         out << "</goto_expr>";
252 }
253
254 void XMLCodeGen::writeCallExpr( InlineItem *item )
255 {
256         out << "<call_expr>";
257         writeInlineList( item->children );
258         out << "</call_expr>";
259 }
260
261 void XMLCodeGen::writeNextExpr( InlineItem *item )
262 {
263         out << "<next_expr>";
264         writeInlineList( item->children );
265         out << "</next_expr>";
266 }
267
268 void XMLCodeGen::writeEntry( InlineItem *item )
269 {
270         if ( pd->generatingSectionSubset )
271                 out << "<entry>-1</entry>";
272         else {
273                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
274                 out << "<entry>" << targ->value->alg.stateNum << "</entry>";
275         }
276 }
277
278 void XMLCodeGen::writeActionExec( InlineItem *item )
279 {
280         out << "<exec>";
281         writeInlineList( item->children );
282         out << "</exec>";
283 }
284
285 void XMLCodeGen::writeLmOnLast( InlineItem *item )
286 {
287         out << "<set_tokend>1</set_tokend>";
288
289         if ( item->longestMatchPart->action != 0 ) {
290                 out << "<sub_action>";
291                 writeInlineList( item->longestMatchPart->action->inlineList );
292                 out << "</sub_action>";
293         }
294 }
295
296 void XMLCodeGen::writeLmOnNext( InlineItem *item )
297 {
298         out << "<set_tokend>0</set_tokend>";
299         out << "<hold></hold>";
300
301         if ( item->longestMatchPart->action != 0 ) {
302                 out << "<sub_action>";
303                 writeInlineList( item->longestMatchPart->action->inlineList );
304                 out << "</sub_action>";
305         }
306 }
307
308 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
309 {
310         out << "<exec><get_tokend></get_tokend></exec>";
311
312         if ( item->longestMatchPart->action != 0 ) {
313                 out << "<sub_action>";
314                 writeInlineList( item->longestMatchPart->action->inlineList );
315                 out << "</sub_action>";
316         }
317 }
318
319 void XMLCodeGen::writeLmSwitch( InlineItem *item )
320 {
321         LongestMatch *longestMatch = item->longestMatch;
322         out << "<lm_switch>\n";
323
324         /* We can't put the <exec> here because we may need to handle the error
325          * case and in that case p should not be changed. Instead use a default
326          * label in the switch to adjust p when user actions are not set. An id of
327          * -1 indicates the default. */
328
329         if ( longestMatch->lmSwitchHandlesError ) {
330                 /* If the switch handles error then we should have also forced the
331                  * error state. */
332                 assert( fsm->errState != 0 );
333
334                 out << "        <sub_action id=\"0\">";
335                 out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
336                 out << "</sub_action>\n";
337         }
338         
339         bool needDefault = false;
340         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
341                 if ( lmi->inLmSelect ) {
342                         if ( lmi->action == 0 )
343                                 needDefault = true;
344                         else {
345                                 /* Open the action. Write it with the context that sets up _p 
346                                  * when doing control flow changes from inside the machine. */
347                                 out << "        <sub_action id=\"" << lmi->longestMatchId << "\">";
348                                 out << "<exec><get_tokend></get_tokend></exec>";
349                                 writeInlineList( lmi->action->inlineList );
350                                 out << "</sub_action>\n";
351                         }
352                 }
353         }
354
355         if ( needDefault ) {
356                 out << "        <sub_action id=\"-1\"><exec><get_tokend>"
357                                 "</get_tokend></exec></sub_action>\n";
358         }
359
360         out << "    </lm_switch>";
361 }
362
363 void XMLCodeGen::writeInlineList( InlineList *inlineList )
364 {
365         for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
366                 switch ( item->type ) {
367                 case InlineItem::Text:
368                         writeText( item );
369                         break;
370                 case InlineItem::Goto:
371                         writeGoto( item );
372                         break;
373                 case InlineItem::GotoExpr:
374                         writeGotoExpr( item );
375                         break;
376                 case InlineItem::Call:
377                         writeCall( item );
378                         break;
379                 case InlineItem::CallExpr:
380                         writeCallExpr( item );
381                         break;
382                 case InlineItem::Next:
383                         writeNext( item );
384                         break;
385                 case InlineItem::NextExpr:
386                         writeNextExpr( item );
387                         break;
388                 case InlineItem::Break:
389                         out << "<break></break>";
390                         break;
391                 case InlineItem::Ret: 
392                         out << "<ret></ret>";
393                         break;
394                 case InlineItem::PChar:
395                         out << "<pchar></pchar>";
396                         break;
397                 case InlineItem::Char: 
398                         out << "<char></char>";
399                         break;
400                 case InlineItem::Curs: 
401                         out << "<curs></curs>";
402                         break;
403                 case InlineItem::Targs: 
404                         out << "<targs></targs>";
405                         break;
406                 case InlineItem::Entry:
407                         writeEntry( item );
408                         break;
409
410                 case InlineItem::Hold:
411                         out << "<hold></hold>";
412                         break;
413                 case InlineItem::Exec:
414                         writeActionExec( item );
415                         break;
416
417                 case InlineItem::LmSetActId:
418                         out << "<set_act>" << 
419                                         item->longestMatchPart->longestMatchId << 
420                                         "</set_act>";
421                         break;
422                 case InlineItem::LmSetTokEnd:
423                         out << "<set_tokend>1</set_tokend>";
424                         break;
425
426                 case InlineItem::LmOnLast:
427                         writeLmOnLast( item );
428                         break;
429                 case InlineItem::LmOnNext:
430                         writeLmOnNext( item );
431                         break;
432                 case InlineItem::LmOnLagBehind:
433                         writeLmOnLagBehind( item );
434                         break;
435                 case InlineItem::LmSwitch: 
436                         writeLmSwitch( item );
437                         break;
438
439                 case InlineItem::LmInitAct:
440                         out << "<init_act></init_act>";
441                         break;
442                 case InlineItem::LmInitTokStart:
443                         out << "<init_tokstart></init_tokstart>";
444                         break;
445                 case InlineItem::LmSetTokStart:
446                         out << "<set_tokstart></set_tokstart>";
447                         break;
448                 }
449         }
450 }
451
452 BackendGen::BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, InputData &inputData )
453 :
454         GenBase(fsmName, pd, fsm, inputData)
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, long entryId, GenInlineItem::Type type )
468 {
469         long targetState;
470         if ( pd->generatingSectionSubset )
471                 targetState = -1;
472         else {
473                 EntryMapEl *targ = fsm->entryPoints.find( entryId );
474                 targetState = targ->value->alg.stateNum;
475         }
476
477         /* Make the item. */
478         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
479         inlineItem->targId = targetState;
480         outList->append( inlineItem );
481 }
482
483 /* Make a sublist item with a given type. */
484 void BackendGen::makeSubList( GenInlineList *outList, 
485                 InlineList *inlineList, GenInlineItem::Type type )
486 {
487         /* Fill the sub list. */
488         GenInlineList *subList = new GenInlineList;
489         makeGenInlineList( subList, inlineList );
490
491         /* Make the item. */
492         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
493         inlineItem->children = subList;
494         outList->append( inlineItem );
495 }
496
497 void BackendGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
498 {
499         makeSetTokend( outList, 1 );
500
501         if ( item->longestMatchPart->action != 0 ) {
502                 makeSubList( outList, 
503                                 item->longestMatchPart->action->inlineList, 
504                                 GenInlineItem::SubAction );
505         }
506 }
507
508 void BackendGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
509 {
510         makeSetTokend( outList, 0 );
511         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
512
513         if ( item->longestMatchPart->action != 0 ) {
514                 makeSubList( outList, 
515                         item->longestMatchPart->action->inlineList,
516                         GenInlineItem::SubAction );
517         }
518 }
519
520 void BackendGen::makeExecGetTokend( GenInlineList *outList )
521 {
522         /* Make the Exec item. */
523         GenInlineItem *execItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
524         execItem->children = new GenInlineList;
525
526         /* Make the GetTokEnd */
527         GenInlineItem *getTokend = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
528         execItem->children->append( getTokend );
529
530         outList->append( execItem );
531 }
532
533 void BackendGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
534 {
535         /* Jump to the tokend. */
536         makeExecGetTokend( outList );
537
538         if ( item->longestMatchPart->action != 0 ) {
539                 makeSubList( outList,
540                         item->longestMatchPart->action->inlineList,
541                         GenInlineItem::SubAction );
542         }
543 }
544
545 void BackendGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
546 {
547         GenInlineItem *lmSwitch = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
548         GenInlineList *lmList = lmSwitch->children = new GenInlineList;
549         LongestMatch *longestMatch = item->longestMatch;
550
551         /* We can't put the <exec> here because we may need to handle the error
552          * case and in that case p should not be changed. Instead use a default
553          * label in the switch to adjust p when user actions are not set. An id of
554          * -1 indicates the default. */
555
556         if ( longestMatch->lmSwitchHandlesError ) {
557                 /* If the switch handles error then we should have also forced the
558                  * error state. */
559                 assert( fsm->errState != 0 );
560
561                 GenInlineItem *errCase = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
562                 errCase->lmId = 0;
563                 errCase->children = new GenInlineList;
564
565                 /* Make the item. */
566                 GenInlineItem *gotoItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
567                 gotoItem->targId = fsm->errState->alg.stateNum;
568                 errCase->children->append( gotoItem );
569
570                 lmList->append( errCase );
571         }
572         
573         bool needDefault = false;
574         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
575                 if ( lmi->inLmSelect ) {
576                         if ( lmi->action == 0 )
577                                 needDefault = true;
578                         else {
579                                 /* Open the action. Write it with the context that sets up _p 
580                                  * when doing control flow changes from inside the machine. */
581                                 GenInlineItem *lmCase = new GenInlineItem( InputLoc(), 
582                                                 GenInlineItem::SubAction );
583                                 lmCase->lmId = lmi->longestMatchId;
584                                 lmCase->children = new GenInlineList;
585
586                                 makeExecGetTokend( lmCase->children );
587                                 makeGenInlineList( lmCase->children, lmi->action->inlineList );
588
589                                 lmList->append( lmCase );
590                         }
591                 }
592         }
593
594         if ( needDefault ) {
595                 GenInlineItem *defCase = new GenInlineItem( InputLoc(), 
596                                 GenInlineItem::SubAction );
597                 defCase->lmId = -1;
598                 defCase->children = new GenInlineList;
599
600                 makeExecGetTokend( defCase->children );
601
602                 lmList->append( defCase );
603         }
604
605         outList->append( lmSwitch );
606 }
607
608 void BackendGen::makeSetTokend( GenInlineList *outList, long offset )
609 {
610         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
611         inlineItem->offset = offset;
612         outList->append( inlineItem );
613 }
614
615 void BackendGen::makeSetAct( GenInlineList *outList, long lmId )
616 {
617         GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
618         inlineItem->lmId = lmId;
619         outList->append( inlineItem );
620 }
621
622 void BackendGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
623 {
624         for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
625                 switch ( item->type ) {
626                 case InlineItem::Text:
627                         makeText( outList, item );
628                         break;
629                 case InlineItem::Goto:
630                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Goto );
631                         break;
632                 case InlineItem::GotoExpr:
633                         makeSubList( outList, item->children, GenInlineItem::GotoExpr );
634                         break;
635                 case InlineItem::Call:
636                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Call );
637                         break;
638                 case InlineItem::CallExpr:
639                         makeSubList( outList, item->children, GenInlineItem::CallExpr );
640                         break;
641                 case InlineItem::Next:
642                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Next );
643                         break;
644                 case InlineItem::NextExpr:
645                         makeSubList( outList, item->children, GenInlineItem::NextExpr );
646                         break;
647                 case InlineItem::Break:
648                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Break ) );
649                         break;
650                 case InlineItem::Ret: 
651                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret ) );
652                         break;
653                 case InlineItem::PChar:
654                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar ) );
655                         break;
656                 case InlineItem::Char: 
657                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Char ) );
658                         break;
659                 case InlineItem::Curs: 
660                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs ) );
661                         break;
662                 case InlineItem::Targs: 
663                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs ) );
664                         break;
665                 case InlineItem::Entry:
666                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Entry );
667                         break;
668
669                 case InlineItem::Hold:
670                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
671                         break;
672                 case InlineItem::Exec:
673                         makeSubList( outList, item->children, GenInlineItem::Exec );
674                         break;
675
676                 case InlineItem::LmSetActId:
677                         makeSetAct( outList, item->longestMatchPart->longestMatchId );
678                         break;
679                 case InlineItem::LmSetTokEnd:
680                         makeSetTokend( outList, 1 );
681                         break;
682
683                 case InlineItem::LmOnLast:
684                         makeLmOnLast( outList, item );
685                         break;
686                 case InlineItem::LmOnNext:
687                         makeLmOnNext( outList, item );
688                         break;
689                 case InlineItem::LmOnLagBehind:
690                         makeLmOnLagBehind( outList, item );
691                         break;
692                 case InlineItem::LmSwitch: 
693                         makeLmSwitch( outList, item );
694                         break;
695
696                 case InlineItem::LmInitAct:
697                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ) );
698                         break;
699                 case InlineItem::LmInitTokStart:
700                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ) );
701                         break;
702                 case InlineItem::LmSetTokStart:
703                         outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ) );
704                         inputData.cgd->hasLongestMatch = true;
705                         break;
706                 }
707         }
708 }
709
710
711 void XMLCodeGen::writeAction( Action *action )
712 {
713         out << "      <action id=\"" << action->actionId << "\"";
714         if ( action->name != 0 ) 
715                 out << " name=\"" << action->name << "\"";
716         out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
717         writeInlineList( action->inlineList );
718         out << "</action>\n";
719 }
720
721 void xmlEscapeHost( std::ostream &out, char *data, long len )
722 {
723         char *end = data + len;
724         while ( data != end ) {
725                 switch ( *data ) {
726                 case '<': out << "&lt;"; break;
727                 case '>': out << "&gt;"; break;
728                 case '&': out << "&amp;"; break;
729                 default: out << *data; break;
730                 }
731                 data += 1;
732         }
733 }
734
735 void XMLCodeGen::writeStateActions( StateAp *state )
736 {
737         RedActionTable *toStateActions = 0;
738         if ( state->toStateActionTable.length() > 0 )
739                 toStateActions = actionTableMap.find( state->toStateActionTable );
740
741         RedActionTable *fromStateActions = 0;
742         if ( state->fromStateActionTable.length() > 0 )
743                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
744
745         /* EOF actions go out here only if the state has no eof target. If it has
746          * an eof target then an eof transition will be used instead. */
747         RedActionTable *eofActions = 0;
748         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
749                 eofActions = actionTableMap.find( state->eofActionTable );
750         
751         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
752                 out << "      <state_actions>";
753                 if ( toStateActions != 0 )
754                         out << toStateActions->id;
755                 else
756                         out << "x";
757
758                 if ( fromStateActions != 0 )
759                         out << " " << fromStateActions->id;
760                 else
761                         out << " x";
762
763                 if ( eofActions != 0 )
764                         out << " " << eofActions->id;
765                 else
766                         out << " x";
767
768                 out << "</state_actions>\n";
769         }
770 }
771
772 void XMLCodeGen::writeStateConditions( StateAp *state )
773 {
774         if ( state->stateCondList.length() > 0 ) {
775                 out << "      <cond_list length=\"" << state->stateCondList.length() << "\">\n";
776                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
777                         out << "        <c>";
778                         writeKey( scdi->lowKey );
779                         out << " ";
780                         writeKey( scdi->highKey );
781                         out << " ";
782                         out << scdi->condSpace->condSpaceId;
783                         out << "</c>\n";
784                 }
785                 out << "      </cond_list>\n";
786         }
787 }
788
789 void XMLCodeGen::writeStateList()
790 {
791         /* Write the list of states. */
792         out << "    <state_list length=\"" << fsm->stateList.length() << "\">\n";
793         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
794                 out << "      <state id=\"" << st->alg.stateNum << "\"";
795                 if ( st->isFinState() )
796                         out << " final=\"t\"";
797                 out << ">\n";
798
799                 writeStateActions( st );
800                 writeEofTrans( st );
801                 writeStateConditions( st );
802                 writeTransList( st );
803
804                 out << "      </state>\n";
805
806                 if ( !st.last() )
807                         out << "\n";
808         }
809         out << "    </state_list>\n";
810 }
811
812 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
813 {
814         bool written = false;
815         if ( nameInst->parent != 0 )
816                 written = writeNameInst( nameInst->parent );
817         
818         if ( nameInst->name != 0 ) {
819                 if ( written )
820                         out << '_';
821                 out << nameInst->name;
822                 written = true;
823         }
824
825         return written;
826 }
827
828 void XMLCodeGen::writeEntryPoints()
829 {
830         /* List of entry points other than start state. */
831         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
832                 out << "    <entry_points";
833                 if ( pd->lmRequiresErrorState )
834                         out << " error=\"t\"";
835                 out << ">\n";
836                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
837                         /* Get the name instantiation from nameIndex. */
838                         NameInst *nameInst = pd->nameIndex[en->key];
839                         StateAp *state = en->value;
840                         out << "      <entry name=\"";
841                         writeNameInst( nameInst );
842                         out << "\">" << state->alg.stateNum << "</entry>\n";
843                 }
844                 out << "    </entry_points>\n";
845         }
846 }
847
848 void XMLCodeGen::writeMachine()
849 {
850         /* Open the machine. */
851         out << "  <machine>\n"; 
852         
853         /* Action tables. */
854         reduceActionTables();
855
856         writeActionList();
857         writeActionTableList();
858         writeConditions();
859
860         /* Start state. */
861         out << "    <start_state>" << fsm->startState->alg.stateNum << 
862                         "</start_state>\n";
863         
864         /* Error state. */
865         if ( fsm->errState != 0 ) {
866                 out << "    <error_state>" << fsm->errState->alg.stateNum << 
867                         "</error_state>\n";
868         }
869
870         writeEntryPoints();
871         writeStateList();
872
873         out << "  </machine>\n";
874 }
875
876
877 void XMLCodeGen::writeConditions()
878 {
879         if ( condData->condSpaceMap.length() > 0 ) {
880                 long nextCondSpaceId = 0;
881                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
882                         cs->condSpaceId = nextCondSpaceId++;
883
884                 out << "    <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
885                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
886                         out << "      <cond_space id=\"" << cs->condSpaceId << 
887                                 "\" length=\"" << cs->condSet.length() << "\">";
888                         writeKey( cs->baseKey );
889                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
890                                 out << " " << (*csi)->actionId;
891                         out << "</cond_space>\n";
892                 }
893                 out << "    </cond_space_list>\n";
894         }
895 }
896
897 void XMLCodeGen::writeExports()
898 {
899         if ( pd->exportList.length() > 0 ) {
900                 out << "  <exports>\n";
901                 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
902                         out << "    <ex name=\"" << exp->name << "\">";
903                         writeKey( exp->key );
904                         out << "</ex>\n";
905                 }
906                 out << "  </exports>\n";
907         }
908 }
909
910 void XMLCodeGen::writeXML()
911 {
912         /* Open the definition. */
913         out << "<ragel_def name=\"" << fsmName << "\">\n";
914
915         /* Alphabet type. */
916         out << "  <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
917         
918         /* Getkey expression. */
919         if ( pd->getKeyExpr != 0 ) {
920                 out << "  <getkey>";
921                 writeInlineList( pd->getKeyExpr );
922                 out << "</getkey>\n";
923         }
924
925         /* Access expression. */
926         if ( pd->accessExpr != 0 ) {
927                 out << "  <access>";
928                 writeInlineList( pd->accessExpr );
929                 out << "</access>\n";
930         }
931
932         /* PrePush expression. */
933         if ( pd->prePushExpr != 0 ) {
934                 out << "  <prepush>";
935                 writeInlineList( pd->prePushExpr );
936                 out << "</prepush>\n";
937         }
938
939         /* PostPop expression. */
940         if ( pd->postPopExpr != 0 ) {
941                 out << "  <postpop>";
942                 writeInlineList( pd->postPopExpr );
943                 out << "</postpop>\n";
944         }
945
946         /*
947          * Variable expressions.
948          */
949
950         if ( pd->pExpr != 0 ) {
951                 out << "  <p_expr>";
952                 writeInlineList( pd->pExpr );
953                 out << "</p_expr>\n";
954         }
955         
956         if ( pd->peExpr != 0 ) {
957                 out << "  <pe_expr>";
958                 writeInlineList( pd->peExpr );
959                 out << "</pe_expr>\n";
960         }
961
962         if ( pd->eofExpr != 0 ) {
963                 out << "  <eof_expr>";
964                 writeInlineList( pd->eofExpr );
965                 out << "</eof_expr>\n";
966         }
967         
968         if ( pd->csExpr != 0 ) {
969                 out << "  <cs_expr>";
970                 writeInlineList( pd->csExpr );
971                 out << "</cs_expr>\n";
972         }
973         
974         if ( pd->topExpr != 0 ) {
975                 out << "  <top_expr>";
976                 writeInlineList( pd->topExpr );
977                 out << "</top_expr>\n";
978         }
979         
980         if ( pd->stackExpr != 0 ) {
981                 out << "  <stack_expr>";
982                 writeInlineList( pd->stackExpr );
983                 out << "</stack_expr>\n";
984         }
985         
986         if ( pd->actExpr != 0 ) {
987                 out << "  <act_expr>";
988                 writeInlineList( pd->actExpr );
989                 out << "</act_expr>\n";
990         }
991         
992         if ( pd->tokstartExpr != 0 ) {
993                 out << "  <tokstart_expr>";
994                 writeInlineList( pd->tokstartExpr );
995                 out << "</tokstart_expr>\n";
996         }
997         
998         if ( pd->tokendExpr != 0 ) {
999                 out << "  <tokend_expr>";
1000                 writeInlineList( pd->tokendExpr );
1001                 out << "</tokend_expr>\n";
1002         }
1003         
1004         if ( pd->dataExpr != 0 ) {
1005                 out << "  <data_expr>";
1006                 writeInlineList( pd->dataExpr );
1007                 out << "</data_expr>\n";
1008         }
1009         
1010         writeExports();
1011         
1012         writeMachine();
1013
1014         out <<
1015                 "</ragel_def>\n";
1016 }
1017
1018 void BackendGen::makeExports()
1019 {
1020         for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
1021                 inputData.cgd->exportList.append( new Export( exp->name, exp->key ) );
1022 }
1023
1024 void BackendGen::makeAction( Action *action )
1025 {
1026         GenInlineList *genList = new GenInlineList;
1027         makeGenInlineList( genList, action->inlineList );
1028
1029         inputData.cgd->newAction( inputData.curAction++, action->name, 
1030                         action->loc.line, action->loc.col, 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         inputData.cgd->initActionList( nextActionId );
1045         inputData.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         inputData.cgd->initActionTableList( numTables );
1062         inputData.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 = inputData.cgd->allActionTables + inputData.curActionTable;
1069                 redAct->actListId = inputData.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 = inputData.cgd->allActions + 
1075                                         atel->value->actionId;
1076                 }
1077
1078                 /* Insert into the action table map. */
1079                 inputData.cgd->redFsm->actionMap.insert( redAct );
1080
1081                 inputData.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                 inputData.cgd->initCondSpaceList( listLength );
1096                 inputData.curCondSpace = 0;
1097
1098                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
1099                         long id = cs->condSpaceId;
1100                         inputData.cgd->newCondSpace( inputData.curCondSpace, id, cs->baseKey );
1101                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
1102                                 inputData.cgd->condSpaceItem( inputData.curCondSpace, (*csi)->actionId );
1103                         inputData.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                         inputData.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                         inputData.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                 inputData.cgd->setStateActions( inputData.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                 inputData.cgd->setEofTrans( inputData.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                 inputData.cgd->initStateCondList( inputData.curState, length );
1198                 inputData.curStateCond = 0;
1199
1200                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
1201                         inputData.cgd->addStateCond( inputData.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         inputData.cgd->newTrans( inputData.curState, inputData.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         inputData.cgd->initTransList( inputData.curState, outList.length() );
1239         inputData.curTrans = 0;
1240
1241         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
1242                 makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
1243
1244         inputData.cgd->finishTransList( inputData.curState );
1245 }
1246
1247
1248 void BackendGen::makeStateList()
1249 {
1250         /* Write the list of states. */
1251         long length = fsm->stateList.length();
1252         inputData.cgd->initStateList( length );
1253         inputData.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                 inputData.cgd->setId( inputData.curState, id );
1262
1263                 if ( st->isFinState() )
1264                         inputData.cgd->setFinal( inputData.curState );
1265
1266                 inputData.curState += 1;
1267         }
1268 }
1269
1270
1271 void BackendGen::makeMachine()
1272 {
1273         inputData.cgd->createMachine();
1274
1275         /* Action tables. */
1276         reduceActionTables();
1277
1278         makeActionList();
1279         makeActionTableList();
1280         makeConditions();
1281
1282         /* Start State. */
1283         inputData.cgd->setStartState( fsm->startState->alg.stateNum );
1284
1285         /* Error state. */
1286         if ( fsm->errState != 0 )
1287                 inputData.cgd->setErrorState( fsm->errState->alg.stateNum );
1288
1289         makeEntryPoints();
1290         makeStateList();
1291
1292         inputData.cgd->closeMachine();
1293 }
1294
1295 void BackendGen::open_ragel_def( char *fsmName )
1296 {
1297         CodeGenMapEl *mapEl = inputData.codeGenMap.find( fsmName );
1298         if ( mapEl != 0 )
1299                 inputData.cgd = mapEl->value;
1300         else {
1301                 inputData.cgd = makeCodeGen( inputData.sourceFileName, fsmName, 
1302                                 *inputData.outStream, inputData.wantComplete );
1303                 inputData.codeGenMap.insert( fsmName, inputData.cgd );
1304         }
1305 }
1306
1307 void BackendGen::close_ragel_def()
1308 {
1309         /* Do this before distributing transitions out to singles and defaults
1310          * makes life easier. */
1311         inputData.cgd->redFsm->maxKey = inputData.cgd->findMaxKey();
1312
1313         inputData.cgd->redFsm->assignActionLocs();
1314
1315         /* Find the first final state (The final state with the lowest id). */
1316         inputData.cgd->redFsm->findFirstFinState();
1317
1318         /* Call the user's callback. */
1319         inputData.cgd->finishRagelDef();
1320 }
1321
1322
1323 void BackendGen::makeBackend()
1324 {
1325         /* Open the definition. */
1326         open_ragel_def( fsmName );
1327
1328         /* Alphabet type. */
1329         inputData.cgd->setAlphType( keyOps->alphType->internalName );
1330         
1331         /* Getkey expression. */
1332         if ( pd->getKeyExpr != 0 ) {
1333                 inputData.cgd->getKeyExpr = new GenInlineList;
1334                 makeGenInlineList( inputData.cgd->getKeyExpr, pd->getKeyExpr );
1335         }
1336
1337         /* Access expression. */
1338         if ( pd->accessExpr != 0 ) {
1339                 inputData.cgd->accessExpr = new GenInlineList;
1340                 makeGenInlineList( inputData.cgd->accessExpr, pd->accessExpr );
1341         }
1342
1343         /* PrePush expression. */
1344         if ( pd->prePushExpr != 0 ) {
1345                 inputData.cgd->prePushExpr = new GenInlineList;
1346                 makeGenInlineList( inputData.cgd->prePushExpr, pd->prePushExpr );
1347         }
1348
1349         /* PostPop expression. */
1350         if ( pd->postPopExpr != 0 ) {
1351                 inputData.cgd->postPopExpr = new GenInlineList;
1352                 makeGenInlineList( inputData.cgd->postPopExpr, pd->postPopExpr );
1353         }
1354
1355         /*
1356          * Variable expressions.
1357          */
1358
1359         if ( pd->pExpr != 0 ) {
1360                 inputData.cgd->pExpr = new GenInlineList;
1361                 makeGenInlineList( inputData.cgd->pExpr, pd->pExpr );
1362         }
1363         
1364         if ( pd->peExpr != 0 ) {
1365                 inputData.cgd->peExpr = new GenInlineList;
1366                 makeGenInlineList( inputData.cgd->peExpr, pd->peExpr );
1367         }
1368
1369         if ( pd->eofExpr != 0 ) {
1370                 inputData.cgd->eofExpr = new GenInlineList;
1371                 makeGenInlineList( inputData.cgd->eofExpr, pd->eofExpr );
1372         }
1373         
1374         if ( pd->csExpr != 0 ) {
1375                 inputData.cgd->csExpr = new GenInlineList;
1376                 makeGenInlineList( inputData.cgd->csExpr, pd->csExpr );
1377         }
1378         
1379         if ( pd->topExpr != 0 ) {
1380                 inputData.cgd->topExpr = new GenInlineList;
1381                 makeGenInlineList( inputData.cgd->topExpr, pd->topExpr );
1382         }
1383         
1384         if ( pd->stackExpr != 0 ) {
1385                 inputData.cgd->stackExpr = new GenInlineList;
1386                 makeGenInlineList( inputData.cgd->stackExpr, pd->stackExpr );
1387         }
1388         
1389         if ( pd->actExpr != 0 ) {
1390                 inputData.cgd->actExpr = new GenInlineList;
1391                 makeGenInlineList( inputData.cgd->actExpr, pd->actExpr );
1392         }
1393         
1394         if ( pd->tokstartExpr != 0 ) {
1395                 inputData.cgd->tokstartExpr = new GenInlineList;
1396                 makeGenInlineList( inputData.cgd->tokstartExpr, pd->tokstartExpr );
1397         }
1398         
1399         if ( pd->tokendExpr != 0 ) {
1400                 inputData.cgd->tokendExpr = new GenInlineList;
1401                 makeGenInlineList( inputData.cgd->tokendExpr, pd->tokendExpr );
1402         }
1403         
1404         if ( pd->dataExpr != 0 ) {
1405                 inputData.cgd->dataExpr = new GenInlineList;
1406                 makeGenInlineList( inputData.cgd->dataExpr, pd->dataExpr );
1407         }
1408         
1409         makeExports();
1410         makeMachine();
1411
1412         close_ragel_def();
1413 }
1414
1415