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