Implemented more of the direct access to the backend.
[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 XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, 
34                 std::ostream &out, XmlParser &xmlParser )
35 :
36         fsmName(fsmName),
37         pd(pd),
38         fsm(fsm),
39         out(out),
40         xmlParser(xmlParser),
41         nextActionTableId(0)
42 {
43 }
44
45
46 void XMLCodeGen::writeActionList()
47 {
48         /* Determine which actions to write. */
49         int nextActionId = 0;
50         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
51                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
52                         act->actionId = nextActionId++;
53         }
54
55         /* Write the list. */
56         out << "    <action_list length=\"" << nextActionId << "\">\n";
57         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
58                 if ( act->actionId >= 0 )
59                         writeAction( act );
60         }
61         out << "    </action_list>\n";
62 }
63
64 void XMLCodeGen::writeActionTableList()
65 {
66         /* Must first order the action tables based on their id. */
67         int numTables = nextActionTableId;
68         RedActionTable **tables = new RedActionTable*[numTables];
69         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
70                 tables[at->id] = at;
71
72         out << "    <action_table_list length=\"" << numTables << "\">\n";
73         for ( int t = 0; t < numTables; t++ ) {
74                 out << "      <action_table id=\"" << t << "\" length=\"" << 
75                                 tables[t]->key.length() << "\">";
76                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
77                         out << atel->value->actionId;
78                         if ( ! atel.last() )
79                                 out << " ";
80                 }
81                 out << "</action_table>\n";
82         }
83         out << "    </action_table_list>\n";
84
85         delete[] tables;
86 }
87
88 void XMLCodeGen::reduceActionTables()
89 {
90         /* Reduce the actions tables to a set. */
91         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
92                 RedActionTable *actionTable = 0;
93
94                 /* Reduce To State Actions. */
95                 if ( st->toStateActionTable.length() > 0 ) {
96                         if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
97                                 actionTable->id = nextActionTableId++;
98                 }
99
100                 /* Reduce From State Actions. */
101                 if ( st->fromStateActionTable.length() > 0 ) {
102                         if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
103                                 actionTable->id = nextActionTableId++;
104                 }
105
106                 /* Reduce EOF actions. */
107                 if ( st->eofActionTable.length() > 0 ) {
108                         if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
109                                 actionTable->id = nextActionTableId++;
110                 }
111
112                 /* Loop the transitions and reduce their actions. */
113                 for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
114                         if ( trans->actionTable.length() > 0 ) {
115                                 if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
116                                         actionTable->id = nextActionTableId++;
117                         }
118                 }
119         }
120 }
121
122 void XMLCodeGen::appendTrans( TransListVect &outList, Key lowKey, 
123                 Key highKey, TransAp *trans )
124 {
125         if ( trans->toState != 0 || trans->actionTable.length() > 0 )
126                 outList.append( TransEl( lowKey, highKey, trans ) );
127 }
128
129 void XMLCodeGen::writeKey( Key key )
130 {
131         if ( keyOps->isSigned )
132                 out << key.getVal();
133         else
134                 out << (unsigned long) key.getVal();
135 }
136
137 void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
138 {
139         /* First reduce the action. */
140         RedActionTable *actionTable = 0;
141         if ( trans->actionTable.length() > 0 )
142                 actionTable = actionTableMap.find( trans->actionTable );
143
144         /* Write the transition. */
145         out << "        <t>";
146         writeKey( lowKey );
147         out << " ";
148         writeKey( highKey );
149
150         if ( trans->toState != 0 )
151                 out << " " << trans->toState->alg.stateNum;
152         else
153                 out << " x";
154
155         if ( actionTable != 0 )
156                 out << " " << actionTable->id;
157         else
158                 out << " x";
159         out << "</t>\n";
160 }
161
162 void XMLCodeGen::writeTransList( StateAp *state )
163 {
164         TransListVect outList;
165
166         /* If there is only are no ranges the task is simple. */
167         if ( state->outList.length() > 0 ) {
168                 /* Loop each source range. */
169                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
170                         /* Reduce the transition. If it reduced to anything then add it. */
171                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
172                 }
173         }
174
175         out << "      <trans_list length=\"" << outList.length() << "\">\n";
176         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
177                 writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
178         out << "      </trans_list>\n";
179 }
180
181 void XMLCodeGen::writeEofTrans( StateAp *state )
182 {
183         RedActionTable *eofActions = 0;
184         if ( state->eofActionTable.length() > 0 )
185                 eofActions = actionTableMap.find( state->eofActionTable );
186         
187         /* The <eof_t> is used when there is an eof target, otherwise the eof
188          * action goes into state actions. */
189         if ( state->eofTarget != 0 ) {
190                 out << "      <eof_t>" << state->eofTarget->alg.stateNum;
191
192                 if ( eofActions != 0 )
193                         out << " " << eofActions->id;
194                 else
195                         out << " x"; 
196
197                 out << "</eof_t>" << endl;
198         }
199 }
200
201 void XMLCodeGen::writeText( InlineItem *item )
202 {
203         if ( item->prev == 0 || item->prev->type != InlineItem::Text )
204                 out << "<text>";
205         xmlEscapeHost( out, item->data, strlen(item->data) );
206         if ( item->next == 0 || item->next->type != InlineItem::Text )
207                 out << "</text>";
208 }
209
210 void XMLCodeGen::writeGoto( InlineItem *item )
211 {
212         if ( pd->generatingSectionSubset )
213                 out << "<goto>-1</goto>";
214         else {
215                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
216                 out << "<goto>" << targ->value->alg.stateNum << "</goto>";
217         }
218 }
219
220 void XMLCodeGen::writeCall( InlineItem *item )
221 {
222         if ( pd->generatingSectionSubset )
223                 out << "<call>-1</call>";
224         else {
225                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
226                 out << "<call>" << targ->value->alg.stateNum << "</call>";
227         }
228 }
229
230 void XMLCodeGen::writeNext( InlineItem *item )
231 {
232         if ( pd->generatingSectionSubset )
233                 out << "<next>-1</next>";
234         else {
235                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
236                 out << "<next>" << targ->value->alg.stateNum << "</next>";
237         }
238 }
239
240 void XMLCodeGen::writeGotoExpr( InlineItem *item )
241 {
242         out << "<goto_expr>";
243         writeInlineList( item->children );
244         out << "</goto_expr>";
245 }
246
247 void XMLCodeGen::writeCallExpr( InlineItem *item )
248 {
249         out << "<call_expr>";
250         writeInlineList( item->children );
251         out << "</call_expr>";
252 }
253
254 void XMLCodeGen::writeNextExpr( InlineItem *item )
255 {
256         out << "<next_expr>";
257         writeInlineList( item->children );
258         out << "</next_expr>";
259 }
260
261 void XMLCodeGen::writeEntry( InlineItem *item )
262 {
263         if ( pd->generatingSectionSubset )
264                 out << "<entry>-1</entry>";
265         else {
266                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
267                 out << "<entry>" << targ->value->alg.stateNum << "</entry>";
268         }
269 }
270
271 void XMLCodeGen::writeActionExec( InlineItem *item )
272 {
273         out << "<exec>";
274         writeInlineList( item->children );
275         out << "</exec>";
276 }
277
278 void XMLCodeGen::writeLmOnLast( InlineItem *item )
279 {
280         out << "<set_tokend>1</set_tokend>";
281
282         if ( item->longestMatchPart->action != 0 ) {
283                 out << "<sub_action>";
284                 writeInlineList( item->longestMatchPart->action->inlineList );
285                 out << "</sub_action>";
286         }
287 }
288
289 void XMLCodeGen::writeLmOnNext( InlineItem *item )
290 {
291         out << "<set_tokend>0</set_tokend>";
292         out << "<hold></hold>";
293
294         if ( item->longestMatchPart->action != 0 ) {
295                 out << "<sub_action>";
296                 writeInlineList( item->longestMatchPart->action->inlineList );
297                 out << "</sub_action>";
298         }
299 }
300
301 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
302 {
303         out << "<exec><get_tokend></get_tokend></exec>";
304
305         if ( item->longestMatchPart->action != 0 ) {
306                 out << "<sub_action>";
307                 writeInlineList( item->longestMatchPart->action->inlineList );
308                 out << "</sub_action>";
309         }
310 }
311
312 void XMLCodeGen::writeLmSwitch( InlineItem *item )
313 {
314         LongestMatch *longestMatch = item->longestMatch;
315         out << "<lm_switch>\n";
316
317         /* We can't put the <exec> here because we may need to handle the error
318          * case and in that case p should not be changed. Instead use a default
319          * label in the switch to adjust p when user actions are not set. An id of
320          * -1 indicates the default. */
321
322         if ( longestMatch->lmSwitchHandlesError ) {
323                 /* If the switch handles error then we should have also forced the
324                  * error state. */
325                 assert( fsm->errState != 0 );
326
327                 out << "        <sub_action id=\"0\">";
328                 out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
329                 out << "</sub_action>\n";
330         }
331         
332         bool needDefault = false;
333         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
334                 if ( lmi->inLmSelect ) {
335                         if ( lmi->action == 0 )
336                                 needDefault = true;
337                         else {
338                                 /* Open the action. Write it with the context that sets up _p 
339                                  * when doing control flow changes from inside the machine. */
340                                 out << "        <sub_action id=\"" << lmi->longestMatchId << "\">";
341                                 out << "<exec><get_tokend></get_tokend></exec>";
342                                 writeInlineList( lmi->action->inlineList );
343                                 out << "</sub_action>\n";
344                         }
345                 }
346         }
347
348         if ( needDefault ) {
349                 out << "        <sub_action id=\"-1\"><exec><get_tokend>"
350                                 "</get_tokend></exec></sub_action>\n";
351         }
352
353         out << "    </lm_switch>";
354 }
355
356 void XMLCodeGen::writeInlineList( InlineList *inlineList )
357 {
358         for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
359                 switch ( item->type ) {
360                 case InlineItem::Text:
361                         writeText( item );
362                         break;
363                 case InlineItem::Goto:
364                         writeGoto( item );
365                         break;
366                 case InlineItem::GotoExpr:
367                         writeGotoExpr( item );
368                         break;
369                 case InlineItem::Call:
370                         writeCall( item );
371                         break;
372                 case InlineItem::CallExpr:
373                         writeCallExpr( item );
374                         break;
375                 case InlineItem::Next:
376                         writeNext( item );
377                         break;
378                 case InlineItem::NextExpr:
379                         writeNextExpr( item );
380                         break;
381                 case InlineItem::Break:
382                         out << "<break></break>";
383                         break;
384                 case InlineItem::Ret: 
385                         out << "<ret></ret>";
386                         break;
387                 case InlineItem::PChar:
388                         out << "<pchar></pchar>";
389                         break;
390                 case InlineItem::Char: 
391                         out << "<char></char>";
392                         break;
393                 case InlineItem::Curs: 
394                         out << "<curs></curs>";
395                         break;
396                 case InlineItem::Targs: 
397                         out << "<targs></targs>";
398                         break;
399                 case InlineItem::Entry:
400                         writeEntry( item );
401                         break;
402
403                 case InlineItem::Hold:
404                         out << "<hold></hold>";
405                         break;
406                 case InlineItem::Exec:
407                         writeActionExec( item );
408                         break;
409
410                 case InlineItem::LmSetActId:
411                         out << "<set_act>" << 
412                                         item->longestMatchPart->longestMatchId << 
413                                         "</set_act>";
414                         break;
415                 case InlineItem::LmSetTokEnd:
416                         out << "<set_tokend>1</set_tokend>";
417                         break;
418
419                 case InlineItem::LmOnLast:
420                         writeLmOnLast( item );
421                         break;
422                 case InlineItem::LmOnNext:
423                         writeLmOnNext( item );
424                         break;
425                 case InlineItem::LmOnLagBehind:
426                         writeLmOnLagBehind( item );
427                         break;
428                 case InlineItem::LmSwitch: 
429                         writeLmSwitch( item );
430                         break;
431
432                 case InlineItem::LmInitAct:
433                         out << "<init_act></init_act>";
434                         break;
435                 case InlineItem::LmInitTokStart:
436                         out << "<init_tokstart></init_tokstart>";
437                         break;
438                 case InlineItem::LmSetTokStart:
439                         out << "<set_tokstart></set_tokstart>";
440                         break;
441                 }
442         }
443 }
444
445 void XMLCodeGen::makeKey( GenInlineList *outList, Key key )
446 {
447 }
448
449 void XMLCodeGen::makeText( GenInlineList *outList, InlineItem *item )
450 {
451         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Text );
452         inlineItem->data = item->data;
453
454         outList->append( inlineItem );
455 }
456
457 void XMLCodeGen::makeGoto( GenInlineList *outList, InlineItem *item )
458 {
459         long targetState;
460         if ( pd->generatingSectionSubset )
461                 targetState = -1;
462         else {
463                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
464                 targetState = targ->value->alg.stateNum;
465         }
466
467         /* Make the item. */
468         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Goto );
469         inlineItem->targId = targetState;
470         outList->append( inlineItem );
471 }
472
473 void XMLCodeGen::makeGotoExpr( GenInlineList *outList, InlineItem *item )
474 {
475         /* Fill the sub list. */
476         GenInlineList *subList = new GenInlineList;
477         makeGenInlineList( subList, item->children );
478
479         /* Make the item. */
480         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::GotoExpr );
481         inlineItem->children = subList;
482         outList->append( inlineItem );
483 }
484
485 void XMLCodeGen::makeCall( GenInlineList *outList, InlineItem *item )
486 {
487         long targetState;
488         if ( pd->generatingSectionSubset )
489                 targetState = -1;
490         else {
491                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
492                 targetState = targ->value->alg.stateNum;
493         }
494
495         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Call );
496         inlineItem->targId = targetState;
497         outList->append( inlineItem );
498 }
499
500 void XMLCodeGen::makeCallExpr( GenInlineList *outList, InlineItem *item )
501 {
502         /* Fill the sub list. */
503         GenInlineList *subList = new GenInlineList;
504         makeGenInlineList( subList, item->children );
505
506         /* Make the item. */
507         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::CallExpr );
508         inlineItem->children = subList;
509         outList->append( inlineItem );
510 }
511
512 void XMLCodeGen::makeNext( GenInlineList *outList, InlineItem *item )
513 {
514         long targetState;
515         if ( pd->generatingSectionSubset )
516                 targetState = -1;
517         else {
518                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
519                 targetState = targ->value->alg.stateNum;
520         }
521
522         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Next );
523         inlineItem->targId = targetState;
524 }
525
526 void XMLCodeGen::makeNextExpr( GenInlineList *outList, InlineItem *item )
527 {
528         /* Fill the sub list. */
529         GenInlineList *subList = new GenInlineList;
530         makeGenInlineList( subList, item->children );
531
532         /* Make the item. */
533         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::NextExpr );
534         inlineItem->children = subList;
535         outList->append( inlineItem );
536 }
537
538 void XMLCodeGen::makeEntry( GenInlineList *outList, InlineItem *item )
539 {
540         long entryState;
541         if ( pd->generatingSectionSubset )
542                 entryState = -1;
543         else {
544                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
545                 entryState = targ->value->alg.stateNum;
546         }
547
548         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Entry );
549         inlineItem->targId = entryState;
550 }
551
552 void XMLCodeGen::makeLmSetActId( GenInlineList *outList, InlineItem *item )
553 {
554 }
555
556 void XMLCodeGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
557 {
558 }
559
560 void XMLCodeGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
561 {
562 }
563
564 void XMLCodeGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
565 {
566 }
567
568 void XMLCodeGen::makeActionExec( GenInlineList *outList, InlineItem *item )
569 {
570 }
571
572 void XMLCodeGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
573 {
574 }
575
576 void XMLCodeGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
577 {
578         for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
579                 switch ( item->type ) {
580                 case InlineItem::Text:
581                         makeText( outList, item );
582                         break;
583                 case InlineItem::Goto:
584                         makeGoto( outList, item );
585                         break;
586                 case InlineItem::GotoExpr:
587                         makeGotoExpr( outList, item );
588                         break;
589                 case InlineItem::Call:
590                         makeCall( outList, item );
591                         break;
592                 case InlineItem::CallExpr:
593                         makeCallExpr( outList, item );
594                         break;
595                 case InlineItem::Next:
596                         makeNext( outList, item );
597                         break;
598                 case InlineItem::NextExpr:
599                         makeNextExpr( outList, item );
600                         break;
601                 case InlineItem::Break:
602                         out << "<break></break>";
603                         break;
604                 case InlineItem::Ret: 
605                         out << "<ret></ret>";
606                         break;
607                 case InlineItem::PChar:
608                         out << "<pchar></pchar>";
609                         break;
610                 case InlineItem::Char: 
611                         out << "<char></char>";
612                         break;
613                 case InlineItem::Curs: 
614                         out << "<curs></curs>";
615                         break;
616                 case InlineItem::Targs: 
617                         out << "<targs></targs>";
618                         break;
619                 case InlineItem::Entry:
620                         makeEntry( outList, item );
621                         break;
622
623                 case InlineItem::Hold:
624                         out << "<hold></hold>";
625                         break;
626                 case InlineItem::Exec:
627                         makeActionExec( outList, item );
628                         break;
629
630                 case InlineItem::LmSetActId:
631                         out << "<set_act>" << 
632                                         item->longestMatchPart->longestMatchId << 
633                                         "</set_act>";
634                         break;
635                 case InlineItem::LmSetTokEnd:
636                         out << "<set_tokend>1</set_tokend>";
637                         break;
638
639                 case InlineItem::LmOnLast:
640                         makeLmOnLast( outList, item );
641                         break;
642                 case InlineItem::LmOnNext:
643                         makeLmOnNext( outList, item );
644                         break;
645                 case InlineItem::LmOnLagBehind:
646                         makeLmOnLagBehind( outList, item );
647                         break;
648                 case InlineItem::LmSwitch: 
649                         makeLmSwitch( outList, item );
650                         break;
651
652                 case InlineItem::LmInitAct:
653                         out << "<init_act></init_act>";
654                         break;
655                 case InlineItem::LmInitTokStart:
656                         out << "<init_tokstart></init_tokstart>";
657                         break;
658                 case InlineItem::LmSetTokStart:
659                         out << "<set_tokstart></set_tokstart>";
660                         break;
661                 }
662         }
663 }
664
665
666 void XMLCodeGen::writeAction( Action *action )
667 {
668         out << "      <action id=\"" << action->actionId << "\"";
669         if ( action->name != 0 ) 
670                 out << " name=\"" << action->name << "\"";
671         out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
672         writeInlineList( action->inlineList );
673         out << "</action>\n";
674 }
675
676 void xmlEscapeHost( std::ostream &out, char *data, long len )
677 {
678         char *end = data + len;
679         while ( data != end ) {
680                 switch ( *data ) {
681                 case '<': out << "&lt;"; break;
682                 case '>': out << "&gt;"; break;
683                 case '&': out << "&amp;"; break;
684                 default: out << *data; break;
685                 }
686                 data += 1;
687         }
688 }
689
690 void XMLCodeGen::writeStateActions( StateAp *state )
691 {
692         RedActionTable *toStateActions = 0;
693         if ( state->toStateActionTable.length() > 0 )
694                 toStateActions = actionTableMap.find( state->toStateActionTable );
695
696         RedActionTable *fromStateActions = 0;
697         if ( state->fromStateActionTable.length() > 0 )
698                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
699
700         /* EOF actions go out here only if the state has no eof target. If it has
701          * an eof target then an eof transition will be used instead. */
702         RedActionTable *eofActions = 0;
703         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
704                 eofActions = actionTableMap.find( state->eofActionTable );
705         
706         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
707                 out << "      <state_actions>";
708                 if ( toStateActions != 0 )
709                         out << toStateActions->id;
710                 else
711                         out << "x";
712
713                 if ( fromStateActions != 0 )
714                         out << " " << fromStateActions->id;
715                 else
716                         out << " x";
717
718                 if ( eofActions != 0 )
719                         out << " " << eofActions->id;
720                 else
721                         out << " x";
722
723                 out << "</state_actions>\n";
724         }
725 }
726
727 void XMLCodeGen::writeStateConditions( StateAp *state )
728 {
729         if ( state->stateCondList.length() > 0 ) {
730                 out << "      <cond_list length=\"" << state->stateCondList.length() << "\">\n";
731                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
732                         out << "        <c>";
733                         writeKey( scdi->lowKey );
734                         out << " ";
735                         writeKey( scdi->highKey );
736                         out << " ";
737                         out << scdi->condSpace->condSpaceId;
738                         out << "</c>\n";
739                 }
740                 out << "      </cond_list>\n";
741         }
742 }
743
744 void XMLCodeGen::writeStateList()
745 {
746         /* Write the list of states. */
747         out << "    <state_list length=\"" << fsm->stateList.length() << "\">\n";
748         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
749                 out << "      <state id=\"" << st->alg.stateNum << "\"";
750                 if ( st->isFinState() )
751                         out << " final=\"t\"";
752                 out << ">\n";
753
754                 writeStateActions( st );
755                 writeEofTrans( st );
756                 writeStateConditions( st );
757                 writeTransList( st );
758
759                 out << "      </state>\n";
760
761                 if ( !st.last() )
762                         out << "\n";
763         }
764         out << "    </state_list>\n";
765 }
766
767 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
768 {
769         bool written = false;
770         if ( nameInst->parent != 0 )
771                 written = writeNameInst( nameInst->parent );
772         
773         if ( nameInst->name != 0 ) {
774                 if ( written )
775                         out << '_';
776                 out << nameInst->name;
777                 written = true;
778         }
779
780         return written;
781 }
782
783 void XMLCodeGen::writeEntryPoints()
784 {
785         /* List of entry points other than start state. */
786         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
787                 out << "    <entry_points";
788                 if ( pd->lmRequiresErrorState )
789                         out << " error=\"t\"";
790                 out << ">\n";
791                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
792                         /* Get the name instantiation from nameIndex. */
793                         NameInst *nameInst = pd->nameIndex[en->key];
794                         StateAp *state = en->value;
795                         out << "      <entry name=\"";
796                         writeNameInst( nameInst );
797                         out << "\">" << state->alg.stateNum << "</entry>\n";
798                 }
799                 out << "    </entry_points>\n";
800         }
801 }
802
803 void XMLCodeGen::writeMachine()
804 {
805         /* Open the machine. */
806         out << "  <machine>\n"; 
807         
808         /* Action tables. */
809         reduceActionTables();
810
811         writeActionList();
812         writeActionTableList();
813         writeConditions();
814
815         /* Start state. */
816         out << "    <start_state>" << fsm->startState->alg.stateNum << 
817                         "</start_state>\n";
818         
819         /* Error state. */
820         if ( fsm->errState != 0 ) {
821                 out << "    <error_state>" << fsm->errState->alg.stateNum << 
822                         "</error_state>\n";
823         }
824
825         writeEntryPoints();
826         writeStateList();
827
828         out << "  </machine>\n";
829 }
830
831
832 void XMLCodeGen::writeConditions()
833 {
834         if ( condData->condSpaceMap.length() > 0 ) {
835                 long nextCondSpaceId = 0;
836                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
837                         cs->condSpaceId = nextCondSpaceId++;
838
839                 out << "    <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
840                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
841                         out << "      <cond_space id=\"" << cs->condSpaceId << 
842                                 "\" length=\"" << cs->condSet.length() << "\">";
843                         writeKey( cs->baseKey );
844                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
845                                 out << " " << (*csi)->actionId;
846                         out << "</cond_space>\n";
847                 }
848                 out << "    </cond_space_list>\n";
849         }
850 }
851
852 void XMLCodeGen::writeExports()
853 {
854         if ( pd->exportList.length() > 0 ) {
855                 out << "  <exports>\n";
856                 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
857                         out << "    <ex name=\"" << exp->name << "\">";
858                         writeKey( exp->key );
859                         out << "</ex>\n";
860                 }
861                 out << "  </exports>\n";
862         }
863 }
864
865 void XMLCodeGen::writeXML()
866 {
867         /* Open the definition. */
868         xmlParser.open_ragel_def( fsmName );
869
870         /* Alphabet type. */
871         xmlParser.cgd->setAlphType( keyOps->alphType->internalName );
872         
873         /* Getkey expression. */
874         if ( pd->getKeyExpr != 0 ) {
875                 out << "  <getkey>";
876                 writeInlineList( pd->getKeyExpr );
877                 out << "</getkey>\n";
878         }
879
880         /* Access expression. */
881         if ( pd->accessExpr != 0 ) {
882                 out << "  <access>";
883                 writeInlineList( pd->accessExpr );
884                 out << "</access>\n";
885         }
886
887         /* PrePush expression. */
888         if ( pd->prePushExpr != 0 ) {
889                 out << "  <prepush>";
890                 writeInlineList( pd->prePushExpr );
891                 out << "</prepush>\n";
892         }
893
894         /* PostPop expression. */
895         if ( pd->postPopExpr != 0 ) {
896                 out << "  <postpop>";
897                 writeInlineList( pd->postPopExpr );
898                 out << "</postpop>\n";
899         }
900
901         /*
902          * Variable expressions.
903          */
904
905         if ( pd->pExpr != 0 ) {
906                 out << "  <p_expr>";
907                 writeInlineList( pd->pExpr );
908                 out << "</p_expr>\n";
909         }
910         
911         if ( pd->peExpr != 0 ) {
912                 out << "  <pe_expr>";
913                 writeInlineList( pd->peExpr );
914                 out << "</pe_expr>\n";
915         }
916
917         if ( pd->eofExpr != 0 ) {
918                 out << "  <eof_expr>";
919                 writeInlineList( pd->eofExpr );
920                 out << "</eof_expr>\n";
921         }
922         
923         if ( pd->csExpr != 0 ) {
924                 out << "  <cs_expr>";
925                 writeInlineList( pd->csExpr );
926                 out << "</cs_expr>\n";
927         }
928         
929         if ( pd->topExpr != 0 ) {
930                 out << "  <top_expr>";
931                 writeInlineList( pd->topExpr );
932                 out << "</top_expr>\n";
933         }
934         
935         if ( pd->stackExpr != 0 ) {
936                 out << "  <stack_expr>";
937                 writeInlineList( pd->stackExpr );
938                 out << "</stack_expr>\n";
939         }
940         
941         if ( pd->actExpr != 0 ) {
942                 out << "  <act_expr>";
943                 writeInlineList( pd->actExpr );
944                 out << "</act_expr>\n";
945         }
946         
947         if ( pd->tokstartExpr != 0 ) {
948                 out << "  <tokstart_expr>";
949                 writeInlineList( pd->tokstartExpr );
950                 out << "</tokstart_expr>\n";
951         }
952         
953         if ( pd->tokendExpr != 0 ) {
954                 out << "  <tokend_expr>";
955                 writeInlineList( pd->tokendExpr );
956                 out << "</tokend_expr>\n";
957         }
958         
959         if ( pd->dataExpr != 0 ) {
960                 out << "  <data_expr>";
961                 writeInlineList( pd->dataExpr );
962                 out << "</data_expr>\n";
963         }
964         
965         writeExports();
966         
967         writeMachine();
968
969         out <<
970                 "</ragel_def>\n";
971 }
972
973 void XMLCodeGen::makeBackend()
974 {
975         /* Open the definition. */
976         xmlParser.open_ragel_def( fsmName );
977
978         /* Alphabet type. */
979         xmlParser.cgd->setAlphType( keyOps->alphType->internalName );
980         
981         /* Getkey expression. */
982         if ( pd->getKeyExpr != 0 ) {
983                 out << "  <getkey>";
984                 writeInlineList( pd->getKeyExpr );
985                 out << "</getkey>\n";
986         }
987
988         /* Access expression. */
989         if ( pd->accessExpr != 0 ) {
990                 out << "  <access>";
991                 writeInlineList( pd->accessExpr );
992                 out << "</access>\n";
993         }
994
995         /* PrePush expression. */
996         if ( pd->prePushExpr != 0 ) {
997                 out << "  <prepush>";
998                 writeInlineList( pd->prePushExpr );
999                 out << "</prepush>\n";
1000         }
1001
1002         /* PostPop expression. */
1003         if ( pd->postPopExpr != 0 ) {
1004                 out << "  <postpop>";
1005                 writeInlineList( pd->postPopExpr );
1006                 out << "</postpop>\n";
1007         }
1008
1009         /*
1010          * Variable expressions.
1011          */
1012
1013         if ( pd->pExpr != 0 ) {
1014                 out << "  <p_expr>";
1015                 writeInlineList( pd->pExpr );
1016                 out << "</p_expr>\n";
1017         }
1018         
1019         if ( pd->peExpr != 0 ) {
1020                 out << "  <pe_expr>";
1021                 writeInlineList( pd->peExpr );
1022                 out << "</pe_expr>\n";
1023         }
1024
1025         if ( pd->eofExpr != 0 ) {
1026                 out << "  <eof_expr>";
1027                 writeInlineList( pd->eofExpr );
1028                 out << "</eof_expr>\n";
1029         }
1030         
1031         if ( pd->csExpr != 0 ) {
1032                 out << "  <cs_expr>";
1033                 writeInlineList( pd->csExpr );
1034                 out << "</cs_expr>\n";
1035         }
1036         
1037         if ( pd->topExpr != 0 ) {
1038                 out << "  <top_expr>";
1039                 writeInlineList( pd->topExpr );
1040                 out << "</top_expr>\n";
1041         }
1042         
1043         if ( pd->stackExpr != 0 ) {
1044                 out << "  <stack_expr>";
1045                 writeInlineList( pd->stackExpr );
1046                 out << "</stack_expr>\n";
1047         }
1048         
1049         if ( pd->actExpr != 0 ) {
1050                 out << "  <act_expr>";
1051                 writeInlineList( pd->actExpr );
1052                 out << "</act_expr>\n";
1053         }
1054         
1055         if ( pd->tokstartExpr != 0 ) {
1056                 out << "  <tokstart_expr>";
1057                 writeInlineList( pd->tokstartExpr );
1058                 out << "</tokstart_expr>\n";
1059         }
1060         
1061         if ( pd->tokendExpr != 0 ) {
1062                 out << "  <tokend_expr>";
1063                 writeInlineList( pd->tokendExpr );
1064                 out << "</tokend_expr>\n";
1065         }
1066         
1067         if ( pd->dataExpr != 0 ) {
1068                 out << "  <data_expr>";
1069                 writeInlineList( pd->dataExpr );
1070                 out << "</data_expr>\n";
1071         }
1072         
1073         writeExports();
1074         
1075         writeMachine();
1076
1077         out <<
1078                 "</ragel_def>\n";
1079 }
1080
1081