Split dotfile generation out into its own executable.
[external/ragel.git] / rlcodegen / flatcodegen.cpp
1 /*
2  *  Copyright 2004-2006 Adrian Thurston <thurston@cs.queensu.ca>
3  *            2004 Erich Ocean <eric.ocean@ampede.com>
4  *            2005 Alan West <alan@alanz.com>
5  */
6
7 /*  This file is part of Ragel.
8  *
9  *  Ragel is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  * 
14  *  Ragel is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  * 
19  *  You should have received a copy of the GNU General Public License
20  *  along with Ragel; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
22  */
23
24 #include "rlcodegen.h"
25 #include "flatcodegen.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28
29 std::ostream &FlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
30 {
31         int act = 0;
32         if ( state->toStateAction != 0 )
33                 act = state->toStateAction->location+1;
34         out << act;
35         return out;
36 }
37
38 std::ostream &FlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
39 {
40         int act = 0;
41         if ( state->fromStateAction != 0 )
42                 act = state->fromStateAction->location+1;
43         out << act;
44         return out;
45 }
46
47 std::ostream &FlatCodeGen::EOF_ACTION( RedStateAp *state )
48 {
49         int act = 0;
50         if ( state->eofAction != 0 )
51                 act = state->eofAction->location+1;
52         out << act;
53         return out;
54 }
55
56 std::ostream &FlatCodeGen::TRANS_ACTION( RedTransAp *trans )
57 {
58         /* If there are actions, emit them. Otherwise emit zero. */
59         int act = 0;
60         if ( trans->action != 0 )
61                 act = trans->action->location+1;
62         out << act;
63         return out;
64 }
65
66 std::ostream &FlatCodeGen::TO_STATE_ACTION_SWITCH()
67 {
68         /* Walk the list of functions, printing the cases. */
69         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
70                 /* Write out referenced actions. */
71                 if ( act->numToStateRefs > 0 ) {
72                         /* Write the case label, the action and the case break */
73                         out << "\tcase " << act->actionId << ":\n";
74                         ACTION( out, act, 0, false );
75                         out << "\tbreak;\n";
76                 }
77         }
78
79         genLineDirective( out );
80         return out;
81 }
82
83 std::ostream &FlatCodeGen::FROM_STATE_ACTION_SWITCH()
84 {
85         /* Walk the list of functions, printing the cases. */
86         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
87                 /* Write out referenced actions. */
88                 if ( act->numFromStateRefs > 0 ) {
89                         /* Write the case label, the action and the case break */
90                         out << "\tcase " << act->actionId << ":\n";
91                         ACTION( out, act, 0, false );
92                         out << "\tbreak;\n";
93                 }
94         }
95
96         genLineDirective( out );
97         return out;
98 }
99
100 std::ostream &FlatCodeGen::EOF_ACTION_SWITCH()
101 {
102         /* Walk the list of functions, printing the cases. */
103         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
104                 /* Write out referenced actions. */
105                 if ( act->numEofRefs > 0 ) {
106                         /* Write the case label, the action and the case break */
107                         out << "\tcase " << act->actionId << ":\n";
108                         ACTION( out, act, 0, true );
109                         out << "\tbreak;\n";
110                 }
111         }
112
113         genLineDirective( out );
114         return out;
115 }
116
117
118 std::ostream &FlatCodeGen::ACTION_SWITCH()
119 {
120         /* Walk the list of functions, printing the cases. */
121         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
122                 /* Write out referenced actions. */
123                 if ( act->numTransRefs > 0 ) {
124                         /* Write the case label, the action and the case break */
125                         out << "\tcase " << act->actionId << ":\n";
126                         ACTION( out, act, 0, false );
127                         out << "\tbreak;\n";
128                 }
129         }
130
131         genLineDirective( out );
132         return out;
133 }
134
135
136 std::ostream &FlatCodeGen::FLAT_INDEX_OFFSET()
137 {
138         out << "\t";
139         int totalStateNum = 0, curIndOffset = 0;
140         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
141                 /* Write the index offset. */
142                 out << curIndOffset;
143                 if ( !st.last() ) {
144                         out << ", ";
145                         if ( ++totalStateNum % IALL == 0 )
146                                 out << "\n\t";
147                 }
148                 
149                 /* Move the index offset ahead. */
150                 if ( st->transList != 0 )
151                         curIndOffset += keyOps->span( st->lowKey, st->highKey );
152
153                 if ( st->defTrans != 0 )
154                         curIndOffset += 1;
155         }
156         out << "\n";
157         return out;
158 }
159
160 std::ostream &FlatCodeGen::KEY_SPANS()
161 {
162         out << "\t";
163         int totalStateNum = 0;
164         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
165                 /* Write singles length. */
166                 unsigned long long span = 0;
167                 if ( st->transList != 0 )
168                         span = keyOps->span( st->lowKey, st->highKey );
169                 out << span;
170                 if ( !st.last() ) {
171                         out << ", ";
172                         if ( ++totalStateNum % IALL == 0 )
173                                 out << "\n\t";
174                 }
175         }
176         out << "\n";
177         return out;
178 }
179
180 std::ostream &FlatCodeGen::TO_STATE_ACTIONS()
181 {
182         out << "\t";
183         int totalStateNum = 0;
184         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
185                 /* Write any eof action. */
186                 TO_STATE_ACTION(st);
187                 if ( !st.last() ) {
188                         out << ", ";
189                         if ( ++totalStateNum % IALL == 0 )
190                                 out << "\n\t";
191                 }
192         }
193         out << "\n";
194         return out;
195 }
196
197 std::ostream &FlatCodeGen::FROM_STATE_ACTIONS()
198 {
199         out << "\t";
200         int totalStateNum = 0;
201         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
202                 /* Write any eof action. */
203                 FROM_STATE_ACTION(st);
204                 if ( !st.last() ) {
205                         out << ", ";
206                         if ( ++totalStateNum % IALL == 0 )
207                                 out << "\n\t";
208                 }
209         }
210         out << "\n";
211         return out;
212 }
213
214 std::ostream &FlatCodeGen::EOF_ACTIONS()
215 {
216         out << "\t";
217         int totalStateNum = 0;
218         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
219                 /* Write any eof action. */
220                 EOF_ACTION(st);
221                 if ( !st.last() ) {
222                         out << ", ";
223                         if ( ++totalStateNum % IALL == 0 )
224                                 out << "\n\t";
225                 }
226         }
227         out << "\n";
228         return out;
229 }
230
231 std::ostream &FlatCodeGen::COND_KEYS()
232 {
233         out << '\t';
234         int totalTrans = 0;
235         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
236                 /* Emit just cond low key and cond high key. */
237                 out << KEY( st->condLowKey ) << ", ";
238                 out << KEY( st->condHighKey ) << ", ";
239                 if ( ++totalTrans % IALL == 0 )
240                         out << "\n\t";
241         }
242
243         /* Output one last number so we don't have to figure out when the last
244          * entry is and avoid writing a comma. */
245         out << 0 << "\n";
246         return out;
247 }
248
249 std::ostream &FlatCodeGen::COND_KEY_SPANS()
250 {
251         out << "\t";
252         int totalStateNum = 0;
253         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
254                 /* Write singles length. */
255                 unsigned long long span = 0;
256                 if ( st->condList != 0 )
257                         span = keyOps->span( st->condLowKey, st->condHighKey );
258                 out << span;
259                 if ( !st.last() ) {
260                         out << ", ";
261                         if ( ++totalStateNum % IALL == 0 )
262                                 out << "\n\t";
263                 }
264         }
265         out << "\n";
266         return out;
267 }
268
269 std::ostream &FlatCodeGen::CONDS()
270 {
271         int totalTrans = 0;
272         out << '\t';
273         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
274                 if ( st->condList != 0 ) {
275                         /* Walk the singles. */
276                         unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
277                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
278                                 if ( st->condList[pos] != 0 )
279                                         out << st->condList[pos]->condSpaceId + 1 << ", ";
280                                 else
281                                         out << "0, ";
282                                 if ( ++totalTrans % IALL == 0 )
283                                         out << "\n\t";
284                         }
285                 }
286         }
287
288         /* Output one last number so we don't have to figure out when the last
289          * entry is and avoid writing a comma. */
290         out << 0 << "\n";
291         return out;
292 }
293
294 std::ostream &FlatCodeGen::COND_INDEX_OFFSET()
295 {
296         out << "\t";
297         int totalStateNum = 0, curIndOffset = 0;
298         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
299                 /* Write the index offset. */
300                 out << curIndOffset;
301                 if ( !st.last() ) {
302                         out << ", ";
303                         if ( ++totalStateNum % IALL == 0 )
304                                 out << "\n\t";
305                 }
306                 
307                 /* Move the index offset ahead. */
308                 if ( st->condList != 0 )
309                         curIndOffset += keyOps->span( st->condLowKey, st->condHighKey );
310         }
311         out << "\n";
312         return out;
313 }
314
315
316 std::ostream &FlatCodeGen::KEYS()
317 {
318         out << '\t';
319         int totalTrans = 0;
320         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
321                 /* Emit just low key and high key. */
322                 out << KEY( st->lowKey ) << ", ";
323                 out << KEY( st->highKey ) << ", ";
324                 if ( ++totalTrans % IALL == 0 )
325                         out << "\n\t";
326         }
327
328         /* Output one last number so we don't have to figure out when the last
329          * entry is and avoid writing a comma. */
330         out << 0 << "\n";
331         return out;
332 }
333
334 std::ostream &FlatCodeGen::INDICIES()
335 {
336         int totalTrans = 0;
337         out << '\t';
338         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
339                 if ( st->transList != 0 ) {
340                         /* Walk the singles. */
341                         unsigned long long span = keyOps->span( st->lowKey, st->highKey );
342                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
343                                 out << st->transList[pos]->id << ", ";
344                                 if ( ++totalTrans % IALL == 0 )
345                                         out << "\n\t";
346                         }
347                 }
348
349                 /* The state's default index goes next. */
350                 if ( st->defTrans != 0 )
351                         out << st->defTrans->id << ", ";
352
353                 if ( ++totalTrans % IALL == 0 )
354                         out << "\n\t";
355         }
356
357         /* Output one last number so we don't have to figure out when the last
358          * entry is and avoid writing a comma. */
359         out << 0 << "\n";
360         return out;
361 }
362
363 std::ostream &FlatCodeGen::TRANS_TARGS()
364 {
365         /* Transitions must be written ordered by their id. */
366         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
367         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
368                 transPtrs[trans->id] = trans;
369
370         /* Keep a count of the num of items in the array written. */
371         out << '\t';
372         int totalStates = 0;
373         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
374                 /* Write out the target state. */
375                 RedTransAp *trans = transPtrs[t];
376                 out << trans->targ->id;
377                 if ( t < redFsm->transSet.length()-1 ) {
378                         out << ", ";
379                         if ( ++totalStates % IALL == 0 )
380                                 out << "\n\t";
381                 }
382         }
383         out << "\n";
384         delete[] transPtrs;
385         return out;
386 }
387
388
389 std::ostream &FlatCodeGen::TRANS_ACTIONS()
390 {
391         /* Transitions must be written ordered by their id. */
392         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
393         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
394                 transPtrs[trans->id] = trans;
395
396         /* Keep a count of the num of items in the array written. */
397         out << '\t';
398         int totalAct = 0;
399         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
400                 /* Write the function for the transition. */
401                 RedTransAp *trans = transPtrs[t];
402                 TRANS_ACTION( trans );
403                 if ( t < redFsm->transSet.length()-1 ) {
404                         out << ", ";
405                         if ( ++totalAct % IALL == 0 )
406                                 out << "\n\t";
407                 }
408         }
409         out << "\n";
410         delete[] transPtrs;
411         return out;
412 }
413
414 void FlatCodeGen::LOCATE_TRANS()
415 {
416         out <<
417                 "       _keys = " << ARR_OFF( K(), "(" + CS() + "<<1)" ) << ";\n"
418                 "       _inds = " << ARR_OFF( I(), IO() + "[" + CS() + "]" ) << ";\n"
419                 "\n"
420                 "       _slen = " << SP() << "[" << CS() << "];\n"
421                 "       _trans = _inds[ _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n"
422                 "               " << GET_WIDE_KEY() << " <= _keys[1] ?\n"
423                 "               " << GET_WIDE_KEY() << " - _keys[0] : _slen ];\n"
424                 "\n";
425 }
426
427 void FlatCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
428 {
429         ret << "{" << CS() << " = " << gotoDest << "; " << 
430                         CTRL_FLOW() << "goto _again;}";
431 }
432
433 void FlatCodeGen::GOTO_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish )
434 {
435         ret << "{" << CS() << " = (";
436         INLINE_LIST( ret, ilItem->children, 0, inFinish );
437         ret << "); " << CTRL_FLOW() << "goto _again;}";
438 }
439
440 void FlatCodeGen::CURS( ostream &ret, bool inFinish )
441 {
442         ret << "(_ps)";
443 }
444
445 void FlatCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
446 {
447         ret << "(" << CS() << ")";
448 }
449
450 void FlatCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
451 {
452         ret << CS() << " = " << nextDest << ";";
453 }
454
455 void FlatCodeGen::NEXT_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish )
456 {
457         ret << CS() << " = (";
458         INLINE_LIST( ret, ilItem->children, 0, inFinish );
459         ret << ");";
460 }
461
462 void FlatCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
463 {
464         ret << "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = " << 
465                         callDest << "; " << CTRL_FLOW() << "goto _again;}";
466 }
467
468
469 void FlatCodeGen::CALL_EXPR( ostream &ret, InlineItem *ilItem, int targState, bool inFinish )
470 {
471         ret << "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = (";
472         INLINE_LIST( ret, ilItem->children, targState, inFinish );
473         ret << "); " << CTRL_FLOW() << "goto _again;}";
474 }
475
476
477 void FlatCodeGen::RET( ostream &ret, bool inFinish )
478 {
479         ret << "{" << CS() << " = " << STACK() << "[--" << TOP() << "]; " << 
480                         CTRL_FLOW() << "goto _again;}";
481 }
482
483 void FlatCodeGen::BREAK( ostream &ret, int targState )
484 {
485         outLabelUsed = true;
486         ret << CTRL_FLOW() << "goto _out;";
487 }
488
489 void FlatCodeGen::writeOutData()
490 {
491         /* If there are any transtion functions then output the array. If there
492          * are none, don't bother emitting an empty array that won't be used. */
493         if ( redFsm->anyActions() ) {
494                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
495                 ACTIONS_ARRAY();
496                 CLOSE_ARRAY() <<
497                 "\n";
498         }
499
500         if ( redFsm->anyConditions() ) {
501                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
502                 COND_KEYS();
503                 CLOSE_ARRAY() <<
504                 "\n";
505
506                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
507                 COND_KEY_SPANS();
508                 CLOSE_ARRAY() <<
509                 "\n";
510
511                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
512                 CONDS();
513                 CLOSE_ARRAY() <<
514                 "\n";
515
516                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
517                 COND_INDEX_OFFSET();
518                 CLOSE_ARRAY() <<
519                 "\n";
520         }
521
522         OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
523         KEYS();
524         CLOSE_ARRAY() <<
525         "\n";
526
527         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
528         KEY_SPANS();
529         CLOSE_ARRAY() <<
530         "\n";
531
532         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
533         FLAT_INDEX_OFFSET();
534         CLOSE_ARRAY() <<
535         "\n";
536
537         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
538         INDICIES();
539         CLOSE_ARRAY() <<
540         "\n";
541
542         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
543         TRANS_TARGS();
544         CLOSE_ARRAY() <<
545         "\n";
546
547         if ( redFsm->anyActions() ) {
548                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
549                 TRANS_ACTIONS();
550                 CLOSE_ARRAY() <<
551                 "\n";
552         }
553
554         if ( redFsm->anyToStateActions() ) {
555                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
556                 TO_STATE_ACTIONS();
557                 CLOSE_ARRAY() <<
558                 "\n";
559         }
560
561         if ( redFsm->anyFromStateActions() ) {
562                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
563                 FROM_STATE_ACTIONS();
564                 CLOSE_ARRAY() <<
565                 "\n";
566         }
567
568         if ( redFsm->anyEofActions() ) {
569                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
570                 EOF_ACTIONS();
571                 CLOSE_ARRAY() <<
572                 "\n";
573         }
574
575         out <<
576                 "static const int " << START() << " = " << START_STATE_ID() << ";\n"
577                 "\n";
578
579         if ( writeFirstFinal ) {
580                 out <<
581                         "static const int " << FIRST_FINAL() << " = " << FIRST_FINAL_STATE() << ";\n"
582                         "\n";
583         }
584
585         if ( writeErr ) {
586                 out <<
587                         "static const int " << ERROR() << " = " << ERROR_STATE() << ";\n"
588                         "\n";
589         }
590 }
591
592 void FlatCodeGen::COND_TRANSLATE()
593 {
594         out << 
595                 "       _widec = " << GET_KEY() << ";\n";
596
597         out <<
598                 "       _keys = " << ARR_OFF( CK(), "(" + CS() + "<<1)" ) << ";\n"
599                 "       _conds = " << ARR_OFF( C(), CO() + "[" + CS() + "]" ) << ";\n"
600                 "\n"
601                 "       _slen = " << CSP() << "[" << CS() << "];\n"
602                 "       _cond = _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n"
603                 "               " << GET_WIDE_KEY() << " <= _keys[1] ?\n"
604                 "               _conds[" << GET_WIDE_KEY() << " - _keys[0]] : 0;\n"
605                 "\n";
606
607         out <<
608                 "       switch ( _cond ) {\n";
609         for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
610                 CondSpace *condSpace = csi;
611                 out << "        case " << condSpace->condSpaceId + 1 << ": {\n";
612                 out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
613                                 KEY(condSpace->baseKey) << " + (" << GET_KEY() << 
614                                 " - " << KEY(keyOps->minKey) << "));\n";
615
616                 for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
617                         out << TABS(2) << "if ( ";
618                         CONDITION( out, *csi );
619                         Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
620                         out << " ) _widec += " << condValOffset << ";\n";
621                 }
622
623                 out << "                }\n";
624                 out << "                break;\n";
625         }
626
627         SWITCH_DEFAULT();
628
629         out <<
630                 "       }\n";
631 }
632
633 void FlatCodeGen::writeOutExec()
634 {
635         outLabelUsed = false;
636
637         out << 
638                 "       {\n"
639                 "       int _slen";
640
641         if ( redFsm->anyRegCurStateRef() )
642                 out << ", _ps";
643
644         out << 
645                 ";\n"
646                 "       int _trans";
647
648         if ( redFsm->anyConditions() )
649                 out << ", _cond";
650         out << ";\n";
651
652         if ( redFsm->anyToStateActions() || 
653                         redFsm->anyRegActions() || redFsm->anyFromStateActions() )
654         {
655                 out << 
656                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << POINTER() << "_acts;\n"
657                         "       " << UINT() << " _nacts;\n"; 
658         }
659
660         out <<
661                 "       " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
662                 "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";
663
664         if ( redFsm->anyConditions() ) {
665                 out << 
666                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxCond) << POINTER() << "_conds;\n"
667                         "       " << WIDE_ALPH_TYPE() << " _widec;\n";
668         }
669
670         out << "\n";
671
672         if ( hasEnd ) {
673                 outLabelUsed = true;
674                 out << 
675                         "       if ( " << P() << " == " << PE() << " )\n"
676                         "               goto _out;\n";
677         }
678         
679         out << "_resume:\n";
680
681         if ( redFsm->errState != 0 ) {
682                 outLabelUsed = true;
683                 out << 
684                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
685                         "               goto _out;\n";
686         }
687
688         if ( redFsm->anyFromStateActions() ) {
689                 out <<
690                         "       _acts = " << ARR_OFF( A(), FSA() + "[" + CS() + "]" ) << ";\n"
691                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
692                         "       while ( _nacts-- > 0 ) {\n"
693                         "               switch ( *_acts++ ) {\n";
694                         FROM_STATE_ACTION_SWITCH();
695                         SWITCH_DEFAULT() <<
696                         "               }\n"
697                         "       }\n"
698                         "\n";
699         }
700
701         if ( redFsm->anyConditions() )
702                 COND_TRANSLATE();
703
704         LOCATE_TRANS();
705
706         if ( redFsm->anyRegCurStateRef() )
707                 out << "        _ps = " << CS() << ";\n";
708
709         out <<
710                 "       " << CS() << " = " << TT() << "[_trans];\n"
711                 "\n";
712
713         if ( redFsm->anyRegActions() ) {
714                 out <<
715                         "       if ( " << TA() << "[_trans] == 0 )\n"
716                         "               goto _again;\n"
717                         "\n"
718                         "       _acts = " << ARR_OFF( A(), TA() + "[_trans]" ) << ";\n"
719                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
720                         "       while ( _nacts-- > 0 ) {\n"
721                         "               switch ( *(_acts++) )\n         {\n";
722                         ACTION_SWITCH();
723                         SWITCH_DEFAULT() <<
724                         "               }\n"
725                         "       }\n"
726                         "\n";
727         }
728
729         if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || 
730                         redFsm->anyActionCalls() || redFsm->anyActionRets() )
731                 out << "_again:\n";
732
733         if ( redFsm->anyToStateActions() ) {
734                 out <<
735                         "       _acts = " << ARR_OFF( A(),  TSA() + "[" + CS() + "]" ) << ";\n"
736                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
737                         "       while ( _nacts-- > 0 ) {\n"
738                         "               switch ( *_acts++ ) {\n";
739                         TO_STATE_ACTION_SWITCH();
740                         SWITCH_DEFAULT() <<
741                         "               }\n"
742                         "       }\n"
743                         "\n";
744         }
745
746         if ( hasEnd ) {
747                 out << 
748                         "       if ( ++" << P() << " != " << PE() << " )\n"
749                         "               goto _resume;\n";
750         }
751         else {
752                 out << 
753                         "       " << P() << " += 1;\n"
754                         "       goto _resume;\n";
755         }
756
757         if ( outLabelUsed )
758                 out << "        _out: {}\n";
759
760         out << "        }\n";
761 }
762
763 void FlatCodeGen::writeOutEOF()
764 {
765         if ( redFsm->anyEofActions() ) {
766                 out << 
767                         "       {\n"
768                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << POINTER() << "_acts = " << 
769                                         ARR_OFF( A(), EA() + "[" + CS() + "]" ) << ";\n"
770                         "       " << UINT() << " _nacts = " << CAST(UINT()) << " *_acts++;\n"
771                         "       while ( _nacts-- > 0 ) {\n"
772                         "               switch ( *_acts++ ) {\n";
773                         EOF_ACTION_SWITCH();
774                         SWITCH_DEFAULT() <<
775                         "               }\n"
776                         "       }\n"
777                         "       }\n"
778                         "\n";
779         }
780 }