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