2 * Copyright 2007 Victor Hugo Borja <vic@rubyforge.org>
3 * 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
6 /* This file is part of Ragel.
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.
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.
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
25 #include "rlgen-ruby.h"
26 #include "rbx-gotocodegen.h"
34 inline string
label(string a
, int i
)
39 ostream
&RbxGotoCodeGen::rbxLabel(ostream
&out
, string label
) {
40 return out
<< "Ruby.asm \"_" << FSM_NAME() << "_" << label
<< ":\"";
43 ostream
&RbxGotoCodeGen::rbxGoto(ostream
&out
, string label
) {
44 return out
<< "Ruby.asm \"goto _" << FSM_NAME() << "_" << label
<< "\"";
47 /* Emit the goto to take for a given transition. */
48 std::ostream
&RbxGotoCodeGen::TRANS_GOTO( RedTransAp
*trans
, int level
)
51 return rbxGoto(out
, label("tr",trans
->id
));
54 std::ostream
&RbxGotoCodeGen::TO_STATE_ACTION_SWITCH()
56 /* Walk the list of functions, printing the cases. */
57 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
58 /* Write out referenced actions. */
59 if ( act
->numToStateRefs
> 0 ) {
60 /* Write the case label, the action and the case break. */
61 out
<< "\twhen " << act
->actionId
<< " then\n";
62 ACTION( out
, act
, 0, false );
66 genLineDirective( out
);
70 std::ostream
&RbxGotoCodeGen::FROM_STATE_ACTION_SWITCH()
72 /* Walk the list of functions, printing the cases. */
73 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
74 /* Write out referenced actions. */
75 if ( act
->numFromStateRefs
> 0 ) {
76 /* Write the case label, the action and the case break. */
77 out
<< "\twhen " << act
->actionId
<< " then\n";
78 ACTION( out
, act
, 0, false );
82 genLineDirective( out
);
86 std::ostream
&RbxGotoCodeGen::EOF_ACTION_SWITCH()
88 /* Walk the list of functions, printing the cases. */
89 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
90 /* Write out referenced actions. */
91 if ( act
->numEofRefs
> 0 ) {
92 /* Write the case label, the action and the case break. */
93 out
<< "\twhen " << act
->actionId
<< " then\n";
94 ACTION( out
, act
, 0, true );
98 genLineDirective( out
);
102 std::ostream
&RbxGotoCodeGen::ACTION_SWITCH()
104 /* Walk the list of functions, printing the cases. */
105 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
106 /* Write out referenced actions. */
107 if ( act
->numTransRefs
> 0 ) {
108 /* Write the case label, the action and the case break. */
109 out
<< "\twhen " << act
->actionId
<< " then\n";
110 ACTION( out
, act
, 0, false );
114 genLineDirective( out
);
118 void RbxGotoCodeGen::GOTO_HEADER( RedStateAp
*state
)
120 /* Label the state. */
121 out
<< "when " << state
->id
<< " then\n";
125 void RbxGotoCodeGen::emitSingleSwitch( RedStateAp
*state
)
127 /* Load up the singles. */
128 int numSingles
= state
->outSingle
.length();
129 RedTransEl
*data
= state
->outSingle
.data
;
131 if ( numSingles
== 1 ) {
132 /* If there is a single single key then write it out as an if. */
133 out
<< "\tif " << GET_WIDE_KEY(state
) << " == " <<
134 KEY(data
[0].lowKey
) << " \n\t\t";
136 /* Virtual function for writing the target of the transition. */
137 TRANS_GOTO(data
[0].value
, 0) << "\n";
141 else if ( numSingles
> 1 ) {
142 /* Write out single keys in a switch if there is more than one. */
143 out
<< "\tcase " << GET_WIDE_KEY(state
) << "\n";
145 /* Write out the single indicies. */
146 for ( int j
= 0; j
< numSingles
; j
++ ) {
147 out
<< "\t\twhen " << KEY(data
[j
].lowKey
) << " then\n";
148 TRANS_GOTO(data
[j
].value
, 0) << "\n";
151 /* Close off the transition switch. */
156 void RbxGotoCodeGen::emitRangeBSearch( RedStateAp
*state
, int level
, int low
, int high
)
158 /* Get the mid position, staying on the lower end of the range. */
159 int mid
= (low
+ high
) >> 1;
160 RedTransEl
*data
= state
->outRange
.data
;
162 /* Determine if we need to look higher or lower. */
163 bool anyLower
= mid
> low
;
164 bool anyHigher
= mid
< high
;
166 /* Determine if the keys at mid are the limits of the alphabet. */
167 bool limitLow
= data
[mid
].lowKey
== keyOps
->minKey
;
168 bool limitHigh
= data
[mid
].highKey
== keyOps
->maxKey
;
170 if ( anyLower
&& anyHigher
) {
171 /* Can go lower and higher than mid. */
172 out
<< TABS(level
) << "if " << GET_WIDE_KEY(state
) << " < " <<
173 KEY(data
[mid
].lowKey
) << " \n";
174 emitRangeBSearch( state
, level
+1, low
, mid
-1 );
175 out
<< TABS(level
) << "elsif " << GET_WIDE_KEY(state
) << " > " <<
176 KEY(data
[mid
].highKey
) << " \n";
177 emitRangeBSearch( state
, level
+1, mid
+1, high
);
178 out
<< TABS(level
) << "else\n";
179 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
180 out
<< TABS(level
) << "end\n";
182 else if ( anyLower
&& !anyHigher
) {
183 /* Can go lower than mid but not higher. */
184 out
<< TABS(level
) << "if " << GET_WIDE_KEY(state
) << " < " <<
185 KEY(data
[mid
].lowKey
) << " then\n";
186 emitRangeBSearch( state
, level
+1, low
, mid
-1 );
188 /* if the higher is the highest in the alphabet then there is no
189 * sense testing it. */
191 out
<< TABS(level
) << "else\n";
192 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
195 out
<< TABS(level
) << "elsif" << GET_WIDE_KEY(state
) << " <= " <<
196 KEY(data
[mid
].highKey
) << " )\n";
197 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
199 out
<< TABS(level
) << "end\n";
201 else if ( !anyLower
&& anyHigher
) {
202 /* Can go higher than mid but not lower. */
203 out
<< TABS(level
) << "if " << GET_WIDE_KEY(state
) << " > " <<
204 KEY(data
[mid
].highKey
) << " \n";
205 emitRangeBSearch( state
, level
+1, mid
+1, high
);
207 /* If the lower end is the lowest in the alphabet then there is no
208 * sense testing it. */
210 out
<< TABS(level
) << "else\n";
211 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
214 out
<< TABS(level
) << "elsif " << GET_WIDE_KEY(state
) << " >= " <<
215 KEY(data
[mid
].lowKey
) << " then\n";
216 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
218 out
<< TABS(level
) << "end\n";
221 /* Cannot go higher or lower than mid. It's mid or bust. What
222 * tests to do depends on limits of alphabet. */
223 if ( !limitLow
&& !limitHigh
) {
224 out
<< TABS(level
) << "if " << KEY(data
[mid
].lowKey
) << " <= " <<
225 GET_WIDE_KEY(state
) << " && " << GET_WIDE_KEY(state
) << " <= " <<
226 KEY(data
[mid
].highKey
) << " \n";
227 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
228 out
<< TABS(level
) << "end\n";
230 else if ( limitLow
&& !limitHigh
) {
231 out
<< TABS(level
) << "if " << GET_WIDE_KEY(state
) << " <= " <<
232 KEY(data
[mid
].highKey
) << " \n";
233 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
234 out
<< TABS(level
) << "end\n";
236 else if ( !limitLow
&& limitHigh
) {
237 out
<< TABS(level
) << "if " << KEY(data
[mid
].lowKey
) << " <= " <<
238 GET_WIDE_KEY(state
) << " \n";
239 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
240 out
<< TABS(level
) << "end\n";
243 /* Both high and low are at the limit. No tests to do. */
244 TRANS_GOTO(data
[mid
].value
, level
+1) << "\n";
249 void RbxGotoCodeGen::STATE_GOTO_ERROR()
251 /* Label the state and bail immediately. */
253 RedStateAp
*state
= redFsm
->errState
;
254 out
<< "when " << state
->id
<< " then\n";
255 rbxGoto(out
<< " ", "_out") << "\n";
258 void RbxGotoCodeGen::COND_TRANSLATE( StateCond
*stateCond
, int level
)
260 CondSpace
*condSpace
= stateCond
->condSpace
;
261 out
<< TABS(level
) << "_widec = " <<
262 KEY(condSpace
->baseKey
) << " + (" << GET_KEY() <<
263 " - " << KEY(keyOps
->minKey
) << ");\n";
265 for ( CondSet::Iter csi
= condSpace
->condSet
; csi
.lte(); csi
++ ) {
266 out
<< TABS(level
) << "if ";
267 CONDITION( out
, *csi
);
268 Size condValOffset
= ((1 << csi
.pos()) * keyOps
->alphSize());
269 out
<< "\n _widec += " << condValOffset
<< ";\n end";
273 void RbxGotoCodeGen::emitCondBSearch( RedStateAp
*state
, int level
, int low
, int high
)
275 /* Get the mid position, staying on the lower end of the range. */
276 int mid
= (low
+ high
) >> 1;
277 StateCond
**data
= state
->stateCondVect
.data
;
279 /* Determine if we need to look higher or lower. */
280 bool anyLower
= mid
> low
;
281 bool anyHigher
= mid
< high
;
283 /* Determine if the keys at mid are the limits of the alphabet. */
284 bool limitLow
= data
[mid
]->lowKey
== keyOps
->minKey
;
285 bool limitHigh
= data
[mid
]->highKey
== keyOps
->maxKey
;
287 if ( anyLower
&& anyHigher
) {
288 /* Can go lower and higher than mid. */
289 out
<< TABS(level
) << "if " << GET_KEY() << " < " <<
290 KEY(data
[mid
]->lowKey
) << " \n";
291 emitCondBSearch( state
, level
+1, low
, mid
-1 );
292 out
<< TABS(level
) << "elsif " << GET_KEY() << " > " <<
293 KEY(data
[mid
]->highKey
) << " \n";
294 emitCondBSearch( state
, level
+1, mid
+1, high
);
295 out
<< TABS(level
) << "else\n";
296 COND_TRANSLATE(data
[mid
], level
+1);
297 out
<< TABS(level
) << "end\n";
299 else if ( anyLower
&& !anyHigher
) {
300 /* Can go lower than mid but not higher. */
301 out
<< TABS(level
) << "if " << GET_KEY() << " < " <<
302 KEY(data
[mid
]->lowKey
) << " \n";
303 emitCondBSearch( state
, level
+1, low
, mid
-1 );
305 /* if the higher is the highest in the alphabet then there is no
306 * sense testing it. */
308 out
<< TABS(level
) << "else\n";
309 COND_TRANSLATE(data
[mid
], level
+1);
312 out
<< TABS(level
) << "elsif " << GET_KEY() << " <= " <<
313 KEY(data
[mid
]->highKey
) << " then\n";
314 COND_TRANSLATE(data
[mid
], level
+1);
316 out
<< TABS(level
) << "end\n";
319 else if ( !anyLower
&& anyHigher
) {
320 /* Can go higher than mid but not lower. */
321 out
<< TABS(level
) << "if " << GET_KEY() << " > " <<
322 KEY(data
[mid
]->highKey
) << " \n";
323 emitCondBSearch( state
, level
+1, mid
+1, high
);
325 /* If the lower end is the lowest in the alphabet then there is no
326 * sense testing it. */
328 out
<< TABS(level
) << "else\n";
329 COND_TRANSLATE(data
[mid
], level
+1);
332 out
<< TABS(level
) << "elsif " << GET_KEY() << " >= " <<
333 KEY(data
[mid
]->lowKey
) << " then\n";
334 COND_TRANSLATE(data
[mid
], level
+1);
336 out
<< TABS(level
) << "end\n";
339 /* Cannot go higher or lower than mid. It's mid or bust. What
340 * tests to do depends on limits of alphabet. */
341 if ( !limitLow
&& !limitHigh
) {
342 out
<< TABS(level
) << "if " << KEY(data
[mid
]->lowKey
) << " <= " <<
343 GET_KEY() << " && " << GET_KEY() << " <= " <<
344 KEY(data
[mid
]->highKey
) << " then\n";
345 COND_TRANSLATE(data
[mid
], level
+1);
346 out
<< TABS(level
) << "end\n";
348 else if ( limitLow
&& !limitHigh
) {
349 out
<< TABS(level
) << "if " << GET_KEY() << " <= " <<
350 KEY(data
[mid
]->highKey
) << " then\n";
351 COND_TRANSLATE(data
[mid
], level
+1);
352 out
<< TABS(level
) << "end\n";
354 else if ( !limitLow
&& limitHigh
) {
355 out
<< TABS(level
) << "if " << KEY(data
[mid
]->lowKey
) << " <= " <<
356 GET_KEY() << " then\n";
357 COND_TRANSLATE(data
[mid
], level
+1);
358 out
<< TABS(level
) << "end\n";
361 /* Both high and low are at the limit. No tests to do. */
362 COND_TRANSLATE(data
[mid
], level
);
367 std::ostream
&RbxGotoCodeGen::STATE_GOTOS()
369 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
370 if ( st
== redFsm
->errState
)
373 /* Writing code above state gotos. */
376 if ( st
->stateCondVect
.length() > 0 ) {
377 out
<< " _widec = " << GET_KEY() << ";\n";
378 emitCondBSearch( st
, 1, 0, st
->stateCondVect
.length() - 1 );
382 if ( st
->outSingle
.length() > 0 )
383 emitSingleSwitch( st
);
385 /* Default case is to binary search for the ranges, if that fails then */
386 if ( st
->outRange
.length() > 0 )
387 emitRangeBSearch( st
, 1, 0, st
->outRange
.length() - 1 );
389 /* Write the default transition. */
390 TRANS_GOTO( st
->defTrans
, 1 ) << "\n";
396 std::ostream
&RbxGotoCodeGen::TRANSITIONS()
398 /* Emit any transitions that have functions and that go to
400 for ( TransApSet::Iter trans
= redFsm
->transSet
; trans
.lte(); trans
++ ) {
401 /* Write the label for the transition so it can be jumped to. */
402 rbxLabel(out
<< " ", label("tr", trans
->id
)) << "\n";
404 /* Destination state. */
405 if ( trans
->action
!= 0 && trans
->action
->anyCurStateRef() )
406 out
<< "_ps = " << CS() << "'n";
407 out
<< CS() << " = " << trans
->targ
->id
<< "\n";
409 if ( trans
->action
!= 0 ) {
410 /* Write out the transition func. */
411 rbxGoto(out
, label("f", trans
->action
->actListId
)) << "\n";
414 /* No code to execute, just loop around. */
415 rbxGoto(out
, "_again") << "\n";
421 std::ostream
&RbxGotoCodeGen::EXEC_FUNCS()
423 /* Make labels that set acts and jump to execFuncs. Loop func indicies. */
424 for ( ActionTableMap::Iter redAct
= redFsm
->actionMap
; redAct
.lte(); redAct
++ ) {
425 if ( redAct
->numTransRefs
> 0 ) {
426 rbxLabel(out
, label("f", redAct
->actListId
)) << "\n" <<
427 "_acts = " << itoa( redAct
->location
+1 ) << "\n";
428 rbxGoto(out
, "execFuncs") << "\n";
432 rbxLabel(out
, "execFuncs") <<
434 " _nacts = " << A() << "[_acts]\n"
436 " while ( _nacts > 0 ) \n"
439 " case ( "<< A() << "[_acts-1] ) \n";
444 rbxGoto(out
, "_again");
448 int RbxGotoCodeGen::TO_STATE_ACTION( RedStateAp
*state
)
451 if ( state
->toStateAction
!= 0 )
452 act
= state
->toStateAction
->location
+1;
456 int RbxGotoCodeGen::FROM_STATE_ACTION( RedStateAp
*state
)
459 if ( state
->fromStateAction
!= 0 )
460 act
= state
->fromStateAction
->location
+1;
464 int RbxGotoCodeGen::EOF_ACTION( RedStateAp
*state
)
467 if ( state
->eofAction
!= 0 )
468 act
= state
->eofAction
->location
+1;
472 std::ostream
&RbxGotoCodeGen::TO_STATE_ACTIONS()
474 /* Take one off for the psuedo start state. */
475 int numStates
= redFsm
->stateList
.length();
476 unsigned int *vals
= new unsigned int[numStates
];
477 memset( vals
, 0, sizeof(unsigned int)*numStates
);
479 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ )
480 vals
[st
->id
] = TO_STATE_ACTION(st
);
483 for ( int st
= 0; st
< redFsm
->nextStateId
; st
++ ) {
484 /* Write any eof action. */
486 if ( st
< numStates
-1 ) {
488 if ( (st
+1) % IALL
== 0 )
497 std::ostream
&RbxGotoCodeGen::FROM_STATE_ACTIONS()
499 /* Take one off for the psuedo start state. */
500 int numStates
= redFsm
->stateList
.length();
501 unsigned int *vals
= new unsigned int[numStates
];
502 memset( vals
, 0, sizeof(unsigned int)*numStates
);
504 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ )
505 vals
[st
->id
] = FROM_STATE_ACTION(st
);
508 for ( int st
= 0; st
< redFsm
->nextStateId
; st
++ ) {
509 /* Write any eof action. */
511 if ( st
< numStates
-1 ) {
513 if ( (st
+1) % IALL
== 0 )
522 std::ostream
&RbxGotoCodeGen::EOF_ACTIONS()
524 /* Take one off for the psuedo start state. */
525 int numStates
= redFsm
->stateList
.length();
526 unsigned int *vals
= new unsigned int[numStates
];
527 memset( vals
, 0, sizeof(unsigned int)*numStates
);
529 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ )
530 vals
[st
->id
] = EOF_ACTION(st
);
533 for ( int st
= 0; st
< redFsm
->nextStateId
; st
++ ) {
534 /* Write any eof action. */
536 if ( st
< numStates
-1 ) {
538 if ( (st
+1) % IALL
== 0 )
547 std::ostream
&RbxGotoCodeGen::FINISH_CASES()
549 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
550 /* States that are final and have an out action need a case. */
551 if ( st
->eofAction
!= 0 ) {
552 /* Write the case label. */
553 out
<< "\t\twhen " << st
->id
<< " then\n";
555 /* Write the goto func. */
556 rbxGoto(out
, label("f", st
->eofAction
->actListId
)) << "\n";
563 void RbxGotoCodeGen::GOTO( ostream
&ret
, int gotoDest
, bool inFinish
)
565 ret
<< "begin\n" << CS() << " = " << gotoDest
<< " ";
566 rbxGoto(ret
, "_again") <<
570 void RbxGotoCodeGen::GOTO_EXPR( ostream
&ret
, InlineItem
*ilItem
, bool inFinish
)
572 ret
<< "begin\n" << CS() << " = (";
573 INLINE_LIST( ret
, ilItem
->children
, 0, inFinish
);
575 rbxGoto(ret
, "_again") <<
579 void RbxGotoCodeGen::CURS( ostream
&ret
, bool inFinish
)
584 void RbxGotoCodeGen::TARGS( ostream
&ret
, bool inFinish
, int targState
)
586 ret
<< "(" << CS() << ")";
589 void RbxGotoCodeGen::NEXT( ostream
&ret
, int nextDest
, bool inFinish
)
591 ret
<< CS() << " = " << nextDest
<< ";";
594 void RbxGotoCodeGen::NEXT_EXPR( ostream
&ret
, InlineItem
*ilItem
, bool inFinish
)
596 ret
<< CS() << " = (";
597 INLINE_LIST( ret
, ilItem
->children
, 0, inFinish
);
601 void RbxGotoCodeGen::CALL( ostream
&ret
, int callDest
, int targState
, bool inFinish
)
603 if ( prePushExpr
!= 0 ) {
605 INLINE_LIST( ret
, prePushExpr
, 0, false );
609 << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = " <<
611 rbxGoto(ret
, "_again") <<
614 if ( prePushExpr
!= 0 )
618 void RbxGotoCodeGen::CALL_EXPR( ostream
&ret
, InlineItem
*ilItem
, int targState
, bool inFinish
)
620 if ( prePushExpr
!= 0 ) {
622 INLINE_LIST( ret
, prePushExpr
, 0, false );
625 ret
<< "begin\n" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = (";
626 INLINE_LIST( ret
, ilItem
->children
, targState
, inFinish
);
628 rbxGoto(ret
, "_again") <<
631 if ( prePushExpr
!= 0 )
635 void RbxGotoCodeGen::RET( ostream
&ret
, bool inFinish
)
637 ret
<< "begin\n" << CS() << " = " << STACK() << "[--" << TOP() << "]; " ;
639 if ( postPopExpr
!= 0 ) {
641 INLINE_LIST( ret
, postPopExpr
, 0, false );
645 rbxGoto(ret
, "_again") <<
649 void RbxGotoCodeGen::BREAK( ostream
&ret
, int targState
)
652 rbxGoto(ret
, "_out") << "\n";
655 void RbxGotoCodeGen::writeData()
657 if ( redFsm
->anyActions() ) {
658 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActArrItem
), A() );
664 if ( redFsm
->anyToStateActions() ) {
665 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), TSA() );
671 if ( redFsm
->anyFromStateActions() ) {
672 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), FSA() );
673 FROM_STATE_ACTIONS();
678 if ( redFsm
->anyEofActions() ) {
679 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), EA() );
688 void RbxGotoCodeGen::writeExec()
690 outLabelUsed
= false;
694 if ( redFsm
->anyRegCurStateRef() )
695 out
<< " _ps = 0;\n";
697 if ( redFsm
->anyToStateActions() || redFsm
->anyRegActions()
698 || redFsm
->anyFromStateActions() )
700 out
<< " _acts, _nacts = nil\n";
703 if ( redFsm
->anyConditions() )
704 out
<< " _widec = nil\n";
711 " if ( " << P() << " == " << PE() << " )\n";
712 rbxGoto(out
<< " ", "_out") << "\n" <<
716 if ( redFsm
->errState
!= 0 ) {
719 " if ( " << CS() << " == " << redFsm
->errState
->id
<< " )\n";
720 rbxGoto(out
<< " ", "_out") << "\n" <<
724 rbxLabel(out
, "_resume") << "\n";
726 if ( redFsm
->anyFromStateActions() ) {
729 " _acts = " << ARR_OFF( A(), FSA() + "[" + CS() + "]" ) << ";\n"
730 " _nacts = " << " *_acts++;\n"
731 " while ( _nacts-- > 0 ) {\n"
732 " switch ( *_acts++ ) {\n";
733 FROM_STATE_ACTION_SWITCH();
741 " case ( " << CS() << " )\n";
749 if ( redFsm
->anyRegActions() )
750 EXEC_FUNCS() << "\n";
753 rbxLabel(out
, "_again") << "\n";
755 if ( redFsm
->anyToStateActions() ) {
757 " _acts = " << ARR_OFF( A(), TSA() + "[" + CS() + "]" ) << ";\n"
758 " _nacts = " << " *_acts++;\n"
759 " while ( _nacts-- > 0 ) {\n"
760 " switch ( *_acts++ ) {\n";
761 TO_STATE_ACTION_SWITCH();
768 if ( redFsm
->errState
!= 0 ) {
771 " if ( " << CS() << " == " << redFsm
->errState
->id
<< " )\n";
772 rbxGoto(out
<< " ", "_out") << "\n" <<
777 out
<< " " << P() << " += 1\n"
778 " if ( " << P() << " != " << PE() << " )\n";
779 rbxGoto(out
<< " ", "_resume") << "\n" <<
784 " " << P() << " += 1;\n";
785 rbxGoto(out
<< " ", "_resume") << "\n";
789 rbxLabel(out
, "_out") << "\n";
794 void RbxGotoCodeGen::writeEOF()
796 if ( redFsm
->anyEofActions() ) {
800 ARR_OFF( A(), EA() + "[" + CS() + "]" ) << ";\n"
801 " " << " _nacts = " << " *_acts++;\n"
802 " while ( _nacts-- > 0 ) {\n"
803 " switch ( *_acts++ ) {\n";
816 * indent-tabs-mode: 1
817 * c-file-style: "bsd"