"Fossies" - the Fresh Open Source Software Archive 
Member "ragel-6.10/ragel/cdgoto.cpp" (24 Mar 2017, 22436 Bytes) of package /linux/misc/ragel-6.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "cdgoto.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
6.9_vs_6.10.
1 /*
2 * Copyright 2001-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 "cdgoto.h"
26 #include "redfsm.h"
27 #include "bstmap.h"
28 #include "gendata.h"
29
30 /* Emit the goto to take for a given transition. */
31 std::ostream &GotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level )
32 {
33 out << TABS(level) << "goto tr" << trans->id << ";";
34 return out;
35 }
36
37 std::ostream &GotoCodeGen::TO_STATE_ACTION_SWITCH()
38 {
39 /* Walk the list of functions, printing the cases. */
40 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
41 /* Write out referenced actions. */
42 if ( act->numToStateRefs > 0 ) {
43 /* Write the case label, the action and the case break. */
44 out << "\tcase " << act->actionId << ":\n";
45 ACTION( out, act, 0, false, false );
46 out << "\tbreak;\n";
47 }
48 }
49
50 genLineDirective( out );
51 return out;
52 }
53
54 std::ostream &GotoCodeGen::FROM_STATE_ACTION_SWITCH()
55 {
56 /* Walk the list of functions, printing the cases. */
57 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
58 /* Write out referenced actions. */
59 if ( act->numFromStateRefs > 0 ) {
60 /* Write the case label, the action and the case break. */
61 out << "\tcase " << act->actionId << ":\n";
62 ACTION( out, act, 0, false, false );
63 out << "\tbreak;\n";
64 }
65 }
66
67 genLineDirective( out );
68 return out;
69 }
70
71 std::ostream &GotoCodeGen::EOF_ACTION_SWITCH()
72 {
73 /* Walk the list of functions, printing the cases. */
74 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
75 /* Write out referenced actions. */
76 if ( act->numEofRefs > 0 ) {
77 /* Write the case label, the action and the case break. */
78 out << "\tcase " << act->actionId << ":\n";
79 ACTION( out, act, 0, true, false );
80 out << "\tbreak;\n";
81 }
82 }
83
84 genLineDirective( out );
85 return out;
86 }
87
88 std::ostream &GotoCodeGen::ACTION_SWITCH()
89 {
90 /* Walk the list of functions, printing the cases. */
91 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
92 /* Write out referenced actions. */
93 if ( act->numTransRefs > 0 ) {
94 /* Write the case label, the action and the case break. */
95 out << "\tcase " << act->actionId << ":\n";
96 ACTION( out, act, 0, false, false );
97 out << "\tbreak;\n";
98 }
99 }
100
101 genLineDirective( out );
102 return out;
103 }
104
105 void GotoCodeGen::GOTO_HEADER( RedStateAp *state )
106 {
107 /* Label the state. */
108 out << "case " << state->id << ":\n";
109 }
110
111
112 void GotoCodeGen::emitSingleSwitch( RedStateAp *state )
113 {
114 /* Load up the singles. */
115 int numSingles = state->outSingle.length();
116 RedTransEl *data = state->outSingle.data;
117
118 if ( numSingles == 1 ) {
119 /* If there is a single single key then write it out as an if. */
120 out << "\tif ( " << GET_WIDE_KEY(state) << " == " <<
121 WIDE_KEY(state, data[0].lowKey) << " )\n\t\t";
122
123 /* Virtual function for writing the target of the transition. */
124 TRANS_GOTO(data[0].value, 0) << "\n";
125 }
126 else if ( numSingles > 1 ) {
127 /* Write out single keys in a switch if there is more than one. */
128 out << "\tswitch( " << GET_WIDE_KEY(state) << " ) {\n";
129
130 /* Write out the single indicies. */
131 for ( int j = 0; j < numSingles; j++ ) {
132 out << "\t\tcase " << WIDE_KEY(state, data[j].lowKey) << ": ";
133 TRANS_GOTO(data[j].value, 0) << "\n";
134 }
135
136 /* Emits a default case for D code. */
137 SWITCH_DEFAULT();
138
139 /* Close off the transition switch. */
140 out << "\t}\n";
141 }
142 }
143
144 void GotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high )
145 {
146 /* Get the mid position, staying on the lower end of the range. */
147 int mid = (low + high) >> 1;
148 RedTransEl *data = state->outRange.data;
149
150 /* Determine if we need to look higher or lower. */
151 bool anyLower = mid > low;
152 bool anyHigher = mid < high;
153
154 /* Determine if the keys at mid are the limits of the alphabet. */
155 bool limitLow = data[mid].lowKey == keyOps->minKey;
156 bool limitHigh = data[mid].highKey == keyOps->maxKey;
157
158 if ( anyLower && anyHigher ) {
159 /* Can go lower and higher than mid. */
160 out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " < " <<
161 WIDE_KEY(state, data[mid].lowKey) << " ) {\n";
162 emitRangeBSearch( state, level+1, low, mid-1 );
163 out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " > " <<
164 WIDE_KEY(state, data[mid].highKey) << " ) {\n";
165 emitRangeBSearch( state, level+1, mid+1, high );
166 out << TABS(level) << "} else\n";
167 TRANS_GOTO(data[mid].value, level+1) << "\n";
168 }
169 else if ( anyLower && !anyHigher ) {
170 /* Can go lower than mid but not higher. */
171 out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " < " <<
172 WIDE_KEY(state, data[mid].lowKey) << " ) {\n";
173 emitRangeBSearch( state, level+1, low, mid-1 );
174
175 /* if the higher is the highest in the alphabet then there is no
176 * sense testing it. */
177 if ( limitHigh ) {
178 out << TABS(level) << "} else\n";
179 TRANS_GOTO(data[mid].value, level+1) << "\n";
180 }
181 else {
182 out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " <= " <<
183 WIDE_KEY(state, data[mid].highKey) << " )\n";
184 TRANS_GOTO(data[mid].value, level+1) << "\n";
185 }
186 }
187 else if ( !anyLower && anyHigher ) {
188 /* Can go higher than mid but not lower. */
189 out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " > " <<
190 WIDE_KEY(state, data[mid].highKey) << " ) {\n";
191 emitRangeBSearch( state, level+1, mid+1, high );
192
193 /* If the lower end is the lowest in the alphabet then there is no
194 * sense testing it. */
195 if ( limitLow ) {
196 out << TABS(level) << "} else\n";
197 TRANS_GOTO(data[mid].value, level+1) << "\n";
198 }
199 else {
200 out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " >= " <<
201 WIDE_KEY(state, data[mid].lowKey) << " )\n";
202 TRANS_GOTO(data[mid].value, level+1) << "\n";
203 }
204 }
205 else {
206 /* Cannot go higher or lower than mid. It's mid or bust. What
207 * tests to do depends on limits of alphabet. */
208 if ( !limitLow && !limitHigh ) {
209 out << TABS(level) << "if ( " << WIDE_KEY(state, data[mid].lowKey) << " <= " <<
210 GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " <<
211 WIDE_KEY(state, data[mid].highKey) << " )\n";
212 TRANS_GOTO(data[mid].value, level+1) << "\n";
213 }
214 else if ( limitLow && !limitHigh ) {
215 out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " <= " <<
216 WIDE_KEY(state, data[mid].highKey) << " )\n";
217 TRANS_GOTO(data[mid].value, level+1) << "\n";
218 }
219 else if ( !limitLow && limitHigh ) {
220 out << TABS(level) << "if ( " << WIDE_KEY(state, data[mid].lowKey) << " <= " <<
221 GET_WIDE_KEY(state) << " )\n";
222 TRANS_GOTO(data[mid].value, level+1) << "\n";
223 }
224 else {
225 /* Both high and low are at the limit. No tests to do. */
226 TRANS_GOTO(data[mid].value, level+1) << "\n";
227 }
228 }
229 }
230
231 void GotoCodeGen::STATE_GOTO_ERROR()
232 {
233 /* Label the state and bail immediately. */
234 outLabelUsed = true;
235 RedStateAp *state = redFsm->errState;
236 out << "case " << state->id << ":\n";
237 out << " goto _out;\n";
238 }
239
240 void GotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level )
241 {
242 GenCondSpace *condSpace = stateCond->condSpace;
243 out << TABS(level) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
244 KEY(condSpace->baseKey) << " + (" << GET_KEY() <<
245 " - " << KEY(keyOps->minKey) << "));\n";
246
247 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
248 out << TABS(level) << "if ( ";
249 CONDITION( out, *csi );
250 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
251 out << " ) _widec += " << condValOffset << ";\n";
252 }
253 }
254
255 void GotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high )
256 {
257 /* Get the mid position, staying on the lower end of the range. */
258 int mid = (low + high) >> 1;
259 GenStateCond **data = state->stateCondVect.data;
260
261 /* Determine if we need to look higher or lower. */
262 bool anyLower = mid > low;
263 bool anyHigher = mid < high;
264
265 /* Determine if the keys at mid are the limits of the alphabet. */
266 bool limitLow = data[mid]->lowKey == keyOps->minKey;
267 bool limitHigh = data[mid]->highKey == keyOps->maxKey;
268
269 if ( anyLower && anyHigher ) {
270 /* Can go lower and higher than mid. */
271 out << TABS(level) << "if ( " << GET_KEY() << " < " <<
272 KEY(data[mid]->lowKey) << " ) {\n";
273 emitCondBSearch( state, level+1, low, mid-1 );
274 out << TABS(level) << "} else if ( " << GET_KEY() << " > " <<
275 KEY(data[mid]->highKey) << " ) {\n";
276 emitCondBSearch( state, level+1, mid+1, high );
277 out << TABS(level) << "} else {\n";
278 COND_TRANSLATE(data[mid], level+1);
279 out << TABS(level) << "}\n";
280 }
281 else if ( anyLower && !anyHigher ) {
282 /* Can go lower than mid but not higher. */
283 out << TABS(level) << "if ( " << GET_KEY() << " < " <<
284 KEY(data[mid]->lowKey) << " ) {\n";
285 emitCondBSearch( state, level+1, low, mid-1 );
286
287 /* if the higher is the highest in the alphabet then there is no
288 * sense testing it. */
289 if ( limitHigh ) {
290 out << TABS(level) << "} else {\n";
291 COND_TRANSLATE(data[mid], level+1);
292 out << TABS(level) << "}\n";
293 }
294 else {
295 out << TABS(level) << "} else if ( " << GET_KEY() << " <= " <<
296 KEY(data[mid]->highKey) << " ) {\n";
297 COND_TRANSLATE(data[mid], level+1);
298 out << TABS(level) << "}\n";
299 }
300 }
301 else if ( !anyLower && anyHigher ) {
302 /* Can go higher than mid but not lower. */
303 out << TABS(level) << "if ( " << GET_KEY() << " > " <<
304 KEY(data[mid]->highKey) << " ) {\n";
305 emitCondBSearch( state, level+1, mid+1, high );
306
307 /* If the lower end is the lowest in the alphabet then there is no
308 * sense testing it. */
309 if ( limitLow ) {
310 out << TABS(level) << "} else {\n";
311 COND_TRANSLATE(data[mid], level+1);
312 out << TABS(level) << "}\n";
313 }
314 else {
315 out << TABS(level) << "} else if ( " << GET_KEY() << " >= " <<
316 KEY(data[mid]->lowKey) << " ) {\n";
317 COND_TRANSLATE(data[mid], level+1);
318 out << TABS(level) << "}\n";
319 }
320 }
321 else {
322 /* Cannot go higher or lower than mid. It's mid or bust. What
323 * tests to do depends on limits of alphabet. */
324 if ( !limitLow && !limitHigh ) {
325 out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " <<
326 GET_KEY() << " && " << GET_KEY() << " <= " <<
327 KEY(data[mid]->highKey) << " ) {\n";
328 COND_TRANSLATE(data[mid], level+1);
329 out << TABS(level) << "}\n";
330 }
331 else if ( limitLow && !limitHigh ) {
332 out << TABS(level) << "if ( " << GET_KEY() << " <= " <<
333 KEY(data[mid]->highKey) << " ) {\n";
334 COND_TRANSLATE(data[mid], level+1);
335 out << TABS(level) << "}\n";
336 }
337 else if ( !limitLow && limitHigh ) {
338 out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " <<
339 GET_KEY() << " )\n {";
340 COND_TRANSLATE(data[mid], level+1);
341 out << TABS(level) << "}\n";
342 }
343 else {
344 /* Both high and low are at the limit. No tests to do. */
345 COND_TRANSLATE(data[mid], level);
346 }
347 }
348 }
349
350 std::ostream &GotoCodeGen::STATE_GOTOS()
351 {
352 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
353 if ( st == redFsm->errState )
354 STATE_GOTO_ERROR();
355 else {
356 /* Writing code above state gotos. */
357 GOTO_HEADER( st );
358
359 if ( st->stateCondVect.length() > 0 ) {
360 out << " _widec = " << GET_KEY() << ";\n";
361 emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 );
362 }
363
364 /* Try singles. */
365 if ( st->outSingle.length() > 0 )
366 emitSingleSwitch( st );
367
368 /* Default case is to binary search for the ranges, if that fails then */
369 if ( st->outRange.length() > 0 )
370 emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 );
371
372 /* Write the default transition. */
373 TRANS_GOTO( st->defTrans, 1 ) << "\n";
374 }
375 }
376 return out;
377 }
378
379 std::ostream &GotoCodeGen::TRANSITIONS()
380 {
381 /* Emit any transitions that have functions and that go to
382 * this state. */
383 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
384 /* Write the label for the transition so it can be jumped to. */
385 out << " tr" << trans->id << ": ";
386
387 /* Destination state. */
388 if ( trans->action != 0 && trans->action->anyCurStateRef() )
389 out << "_ps = " << vCS() << ";";
390 out << vCS() << " = " << trans->targ->id << "; ";
391
392 if ( trans->action != 0 ) {
393 /* Write out the transition func. */
394 out << "goto f" << trans->action->actListId << ";\n";
395 }
396 else {
397 /* No code to execute, just loop around. */
398 out << "goto _again;\n";
399 }
400 }
401 return out;
402 }
403
404 std::ostream &GotoCodeGen::EXEC_FUNCS()
405 {
406 /* Make labels that set acts and jump to execFuncs. Loop func indicies. */
407 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
408 if ( redAct->numTransRefs > 0 ) {
409 out << " f" << redAct->actListId << ": " <<
410 "_acts = " << ARR_OFF(A(), itoa( redAct->location+1 ) ) << ";"
411 " goto execFuncs;\n";
412 }
413 }
414
415 out <<
416 "\n"
417 "execFuncs:\n"
418 " _nacts = *_acts++;\n"
419 " while ( _nacts-- > 0 ) {\n"
420 " switch ( *_acts++ ) {\n";
421 ACTION_SWITCH();
422 SWITCH_DEFAULT() <<
423 " }\n"
424 " }\n"
425 " goto _again;\n";
426 return out;
427 }
428
429 unsigned int GotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
430 {
431 int act = 0;
432 if ( state->toStateAction != 0 )
433 act = state->toStateAction->location+1;
434 return act;
435 }
436
437 unsigned int GotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
438 {
439 int act = 0;
440 if ( state->fromStateAction != 0 )
441 act = state->fromStateAction->location+1;
442 return act;
443 }
444
445 unsigned int GotoCodeGen::EOF_ACTION( RedStateAp *state )
446 {
447 int act = 0;
448 if ( state->eofAction != 0 )
449 act = state->eofAction->location+1;
450 return act;
451 }
452
453 std::ostream &GotoCodeGen::TO_STATE_ACTIONS()
454 {
455 /* Take one off for the psuedo start state. */
456 int numStates = redFsm->stateList.length();
457 unsigned int *vals = new unsigned int[numStates];
458 memset( vals, 0, sizeof(unsigned int)*numStates );
459
460 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
461 vals[st->id] = TO_STATE_ACTION(st);
462
463 out << "\t";
464 for ( int st = 0; st < redFsm->nextStateId; st++ ) {
465 /* Write any eof action. */
466 out << vals[st];
467 if ( st < numStates-1 ) {
468 out << ", ";
469 if ( (st+1) % IALL == 0 )
470 out << "\n\t";
471 }
472 }
473 out << "\n";
474 delete[] vals;
475 return out;
476 }
477
478 std::ostream &GotoCodeGen::FROM_STATE_ACTIONS()
479 {
480 /* Take one off for the psuedo start state. */
481 int numStates = redFsm->stateList.length();
482 unsigned int *vals = new unsigned int[numStates];
483 memset( vals, 0, sizeof(unsigned int)*numStates );
484
485 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
486 vals[st->id] = FROM_STATE_ACTION(st);
487
488 out << "\t";
489 for ( int st = 0; st < redFsm->nextStateId; st++ ) {
490 /* Write any eof action. */
491 out << vals[st];
492 if ( st < numStates-1 ) {
493 out << ", ";
494 if ( (st+1) % IALL == 0 )
495 out << "\n\t";
496 }
497 }
498 out << "\n";
499 delete[] vals;
500 return out;
501 }
502
503 std::ostream &GotoCodeGen::EOF_ACTIONS()
504 {
505 /* Take one off for the psuedo start state. */
506 int numStates = redFsm->stateList.length();
507 unsigned int *vals = new unsigned int[numStates];
508 memset( vals, 0, sizeof(unsigned int)*numStates );
509
510 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
511 vals[st->id] = EOF_ACTION(st);
512
513 out << "\t";
514 for ( int st = 0; st < redFsm->nextStateId; st++ ) {
515 /* Write any eof action. */
516 out << vals[st];
517 if ( st < numStates-1 ) {
518 out << ", ";
519 if ( (st+1) % IALL == 0 )
520 out << "\n\t";
521 }
522 }
523 out << "\n";
524 delete[] vals;
525 return out;
526 }
527
528 std::ostream &GotoCodeGen::FINISH_CASES()
529 {
530 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
531 /* States that are final and have an out action need a case. */
532 if ( st->eofAction != 0 ) {
533 /* Write the case label. */
534 out << "\t\tcase " << st->id << ": ";
535
536 /* Write the goto func. */
537 out << "goto f" << st->eofAction->actListId << ";\n";
538 }
539 }
540
541 return out;
542 }
543
544 void GotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
545 {
546 ret << "{";
547
548 ret << vCS() << " = " << gotoDest << ";";
549
550 if ( inFinish && !noEnd )
551 EOF_CHECK( ret );
552
553 ret << CTRL_FLOW() << "goto _again;";
554
555 ret << "}";
556 }
557
558 void GotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
559 {
560 ret << "{";
561
562 ret << vCS() << " = (";
563 INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
564 ret << ");";
565
566 if ( inFinish && !noEnd )
567 EOF_CHECK( ret );
568
569 ret << CTRL_FLOW() << "goto _again;";
570
571 ret << "}";
572 }
573
574 void GotoCodeGen::CURS( ostream &ret, bool inFinish )
575 {
576 ret << "(_ps)";
577 }
578
579 void GotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
580 {
581 ret << "(" << vCS() << ")";
582 }
583
584 void GotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
585 {
586 ret << vCS() << " = " << nextDest << ";";
587 }
588
589 void GotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
590 {
591 ret << vCS() << " = (";
592 INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
593 ret << ");";
594 }
595
596 void GotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
597 {
598 if ( prePushExpr != 0 ) {
599 ret << "{";
600 INLINE_LIST( ret, prePushExpr, 0, false, false );
601 }
602
603 ret << "{";
604
605 ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";";
606
607 if ( inFinish && !noEnd )
608 EOF_CHECK( ret );
609
610 ret << CTRL_FLOW() << "goto _again;";
611
612 ret << "}";
613
614 if ( prePushExpr != 0 )
615 ret << "}";
616 }
617
618 void GotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
619 {
620 if ( prePushExpr != 0 ) {
621 ret << "{";
622 INLINE_LIST( ret, prePushExpr, 0, false, false );
623 }
624
625 ret << "{";
626
627 ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
628 INLINE_LIST( ret, ilItem->children, targState, inFinish, false );
629 ret << ");";
630
631 if ( inFinish && !noEnd )
632 EOF_CHECK( ret );
633
634 ret << CTRL_FLOW() << "goto _again;";
635
636 ret << "}";
637
638 if ( prePushExpr != 0 )
639 ret << "}";
640 }
641
642 void GotoCodeGen::RET( ostream &ret, bool inFinish )
643 {
644 ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
645
646 if ( postPopExpr != 0 ) {
647 ret << "{";
648 INLINE_LIST( ret, postPopExpr, 0, false, false );
649 ret << "}";
650 }
651
652 if ( inFinish && !noEnd )
653 EOF_CHECK( ret );
654
655 ret << CTRL_FLOW() << "goto _again;";
656 ret << "}";
657 }
658
659 void GotoCodeGen::BREAK( ostream &ret, int targState, bool csForced )
660 {
661 outLabelUsed = true;
662 ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }";
663 }
664
665 void GotoCodeGen::writeData()
666 {
667 if ( redFsm->anyActions() ) {
668 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
669 ACTIONS_ARRAY();
670 CLOSE_ARRAY() <<
671 "\n";
672 }
673
674 if ( redFsm->anyToStateActions() ) {
675 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
676 TO_STATE_ACTIONS();
677 CLOSE_ARRAY() <<
678 "\n";
679 }
680
681 if ( redFsm->anyFromStateActions() ) {
682 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
683 FROM_STATE_ACTIONS();
684 CLOSE_ARRAY() <<
685 "\n";
686 }
687
688 if ( redFsm->anyEofActions() ) {
689 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
690 EOF_ACTIONS();
691 CLOSE_ARRAY() <<
692 "\n";
693 }
694
695 STATE_IDS();
696 }
697
698 void GotoCodeGen::writeExec()
699 {
700 testEofUsed = false;
701 outLabelUsed = false;
702
703 out << " {\n";
704
705 if ( redFsm->anyRegCurStateRef() )
706 out << " int _ps = 0;\n";
707
708 if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
709 || redFsm->anyFromStateActions() )
710 {
711 out <<
712 " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << PTR_CONST_END() << POINTER() << "_acts;\n"
713 " " << UINT() << " _nacts;\n";
714 }
715
716 if ( redFsm->anyConditions() )
717 out << " " << WIDE_ALPH_TYPE() << " _widec;\n";
718
719 out << "\n";
720
721 if ( !noEnd ) {
722 testEofUsed = true;
723 out <<
724 " if ( " << P() << " == " << PE() << " )\n"
725 " goto _test_eof;\n";
726 }
727
728 if ( redFsm->errState != 0 ) {
729 outLabelUsed = true;
730 out <<
731 " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
732 " goto _out;\n";
733 }
734
735 out << "_resume:\n";
736
737 if ( redFsm->anyFromStateActions() ) {
738 out <<
739 " _acts = " << ARR_OFF( A(), FSA() + "[" + vCS() + "]" ) << ";\n"
740 " _nacts = " << CAST(UINT()) << " *_acts++;\n"
741 " while ( _nacts-- > 0 ) {\n"
742 " switch ( *_acts++ ) {\n";
743 FROM_STATE_ACTION_SWITCH();
744 SWITCH_DEFAULT() <<
745 " }\n"
746 " }\n"
747 "\n";
748 }
749
750 out <<
751 " switch ( " << vCS() << " ) {\n";
752 STATE_GOTOS();
753 SWITCH_DEFAULT() <<
754 " }\n"
755 "\n";
756 TRANSITIONS() <<
757 "\n";
758
759 if ( redFsm->anyRegActions() )
760 EXEC_FUNCS() << "\n";
761
762 out << "_again:\n";
763
764 if ( redFsm->anyToStateActions() ) {
765 out <<
766 " _acts = " << ARR_OFF( A(), TSA() + "[" + vCS() + "]" ) << ";\n"
767 " _nacts = " << CAST(UINT()) << " *_acts++;\n"
768 " while ( _nacts-- > 0 ) {\n"
769 " switch ( *_acts++ ) {\n";
770 TO_STATE_ACTION_SWITCH();
771 SWITCH_DEFAULT() <<
772 " }\n"
773 " }\n"
774 "\n";
775 }
776
777 if ( redFsm->errState != 0 ) {
778 outLabelUsed = true;
779 out <<
780 " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
781 " goto _out;\n";
782 }
783
784 if ( !noEnd ) {
785 out <<
786 " if ( ++" << P() << " != " << PE() << " )\n"
787 " goto _resume;\n";
788 }
789 else {
790 out <<
791 " " << P() << " += 1;\n"
792 " goto _resume;\n";
793 }
794
795 if ( testEofUsed )
796 out << " _test_eof: {}\n";
797
798 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
799 out <<
800 " if ( " << P() << " == " << vEOF() << " )\n"
801 " {\n";
802
803 if ( redFsm->anyEofTrans() ) {
804 out <<
805 " switch ( " << vCS() << " ) {\n";
806
807 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
808 if ( st->eofTrans != 0 )
809 out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n";
810 }
811
812 SWITCH_DEFAULT() <<
813 " }\n";
814 }
815
816 if ( redFsm->anyEofActions() ) {
817 out <<
818 " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << PTR_CONST_END() <<
819 POINTER() << "__acts = " <<
820 ARR_OFF( A(), EA() + "[" + vCS() + "]" ) << ";\n"
821 " " << UINT() << " __nacts = " << CAST(UINT()) << " *__acts++;\n"
822 " while ( __nacts-- > 0 ) {\n"
823 " switch ( *__acts++ ) {\n";
824 EOF_ACTION_SWITCH();
825 SWITCH_DEFAULT() <<
826 " }\n"
827 " }\n";
828 }
829
830 out <<
831 " }\n"
832 "\n";
833 }
834
835 if ( outLabelUsed )
836 out << " _out: {}\n";
837
838 out << " }\n";
839 }