Use portable types in the C/C++ code generator
[ragel-jkt.git] / ragel / cstable.cpp
blob72df0a63ae3f5b1ce1a9e3535dd66b044d62326a
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 */
7 /* This file is part of Ragel.
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.
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.
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
24 #include "ragel.h"
25 #include "cstable.h"
26 #include "redfsm.h"
27 #include "gendata.h"
29 /* Determine if we should use indicies or not. */
30 void CSharpTabCodeGen::calcIndexSize()
32 int sizeWithInds = 0, sizeWithoutInds = 0;
34 /* Calculate cost of using with indicies. */
35 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
36 int totalIndex = st->outSingle.length() + st->outRange.length() +
37 (st->defTrans == 0 ? 0 : 1);
38 sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
40 sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
41 if ( redFsm->anyActions() )
42 sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
44 /* Calculate the cost of not using indicies. */
45 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
46 int totalIndex = st->outSingle.length() + st->outRange.length() +
47 (st->defTrans == 0 ? 0 : 1);
48 sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
49 if ( redFsm->anyActions() )
50 sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
53 /* If using indicies reduces the size, use them. */
54 useIndicies = sizeWithInds < sizeWithoutInds;
57 std::ostream &CSharpTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
59 int act = 0;
60 if ( state->toStateAction != 0 )
61 act = state->toStateAction->location+1;
62 out << act;
63 return out;
66 std::ostream &CSharpTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
68 int act = 0;
69 if ( state->fromStateAction != 0 )
70 act = state->fromStateAction->location+1;
71 out << act;
72 return out;
75 std::ostream &CSharpTabCodeGen::EOF_ACTION( RedStateAp *state )
77 int act = 0;
78 if ( state->eofAction != 0 )
79 act = state->eofAction->location+1;
80 out << act;
81 return out;
85 std::ostream &CSharpTabCodeGen::TRANS_ACTION( RedTransAp *trans )
87 /* If there are actions, emit them. Otherwise emit zero. */
88 int act = 0;
89 if ( trans->action != 0 )
90 act = trans->action->location+1;
91 out << act;
92 return out;
95 std::ostream &CSharpTabCodeGen::TO_STATE_ACTION_SWITCH()
97 /* Walk the list of functions, printing the cases. */
98 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
99 /* Write out referenced actions. */
100 if ( act->numToStateRefs > 0 ) {
101 /* Write the case label, the action and the case break. */
102 out << "\tcase " << act->actionId << ":\n";
103 ACTION( out, act, 0, false );
104 out << "\tbreak;\n";
108 genLineDirective( out );
109 return out;
112 std::ostream &CSharpTabCodeGen::FROM_STATE_ACTION_SWITCH()
114 /* Walk the list of functions, printing the cases. */
115 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
116 /* Write out referenced actions. */
117 if ( act->numFromStateRefs > 0 ) {
118 /* Write the case label, the action and the case break. */
119 out << "\tcase " << act->actionId << ":\n";
120 ACTION( out, act, 0, false );
121 out << "\tbreak;\n";
125 genLineDirective( out );
126 return out;
129 std::ostream &CSharpTabCodeGen::EOF_ACTION_SWITCH()
131 /* Walk the list of functions, printing the cases. */
132 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
133 /* Write out referenced actions. */
134 if ( act->numEofRefs > 0 ) {
135 /* Write the case label, the action and the case break. */
136 out << "\tcase " << act->actionId << ":\n";
137 ACTION( out, act, 0, true );
138 out << "\tbreak;\n";
142 genLineDirective( out );
143 return out;
147 std::ostream &CSharpTabCodeGen::ACTION_SWITCH()
149 /* Walk the list of functions, printing the cases. */
150 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
151 /* Write out referenced actions. */
152 if ( act->numTransRefs > 0 ) {
153 /* Write the case label, the action and the case break. */
154 out << "\tcase " << act->actionId << ":\n";
155 ACTION( out, act, 0, false );
156 out << "\tbreak;\n";
160 genLineDirective( out );
161 return out;
164 std::ostream &CSharpTabCodeGen::COND_OFFSETS()
166 out << "\t";
167 int totalStateNum = 0, curKeyOffset = 0;
168 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
169 /* Write the key offset. */
170 out << curKeyOffset;
171 if ( !st.last() ) {
172 out << ", ";
173 if ( ++totalStateNum % IALL == 0 )
174 out << "\n\t";
177 /* Move the key offset ahead. */
178 curKeyOffset += st->stateCondList.length();
180 out << "\n";
181 return out;
184 std::ostream &CSharpTabCodeGen::KEY_OFFSETS()
186 out << "\t";
187 int totalStateNum = 0, curKeyOffset = 0;
188 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
189 /* Write the key offset. */
190 out << curKeyOffset;
191 if ( !st.last() ) {
192 out << ", ";
193 if ( ++totalStateNum % IALL == 0 )
194 out << "\n\t";
197 /* Move the key offset ahead. */
198 curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
200 out << "\n";
201 return out;
205 std::ostream &CSharpTabCodeGen::INDEX_OFFSETS()
207 out << "\t";
208 int totalStateNum = 0, curIndOffset = 0;
209 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
210 /* Write the index offset. */
211 out << curIndOffset;
212 if ( !st.last() ) {
213 out << ", ";
214 if ( ++totalStateNum % IALL == 0 )
215 out << "\n\t";
218 /* Move the index offset ahead. */
219 curIndOffset += st->outSingle.length() + st->outRange.length();
220 if ( st->defTrans != 0 )
221 curIndOffset += 1;
223 out << "\n";
224 return out;
227 std::ostream &CSharpTabCodeGen::COND_LENS()
229 out << "\t";
230 int totalStateNum = 0;
231 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
232 /* Write singles length. */
233 out << st->stateCondList.length();
234 if ( !st.last() ) {
235 out << ", ";
236 if ( ++totalStateNum % IALL == 0 )
237 out << "\n\t";
240 out << "\n";
241 return out;
245 std::ostream &CSharpTabCodeGen::SINGLE_LENS()
247 out << "\t";
248 int totalStateNum = 0;
249 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
250 /* Write singles length. */
251 out << st->outSingle.length();
252 if ( !st.last() ) {
253 out << ", ";
254 if ( ++totalStateNum % IALL == 0 )
255 out << "\n\t";
258 out << "\n";
259 return out;
262 std::ostream &CSharpTabCodeGen::RANGE_LENS()
264 out << "\t";
265 int totalStateNum = 0;
266 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
267 /* Emit length of range index. */
268 out << st->outRange.length();
269 if ( !st.last() ) {
270 out << ", ";
271 if ( ++totalStateNum % IALL == 0 )
272 out << "\n\t";
275 out << "\n";
276 return out;
279 std::ostream &CSharpTabCodeGen::TO_STATE_ACTIONS()
281 out << "\t";
282 int totalStateNum = 0;
283 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
284 /* Write any eof action. */
285 TO_STATE_ACTION(st);
286 if ( !st.last() ) {
287 out << ", ";
288 if ( ++totalStateNum % IALL == 0 )
289 out << "\n\t";
292 out << "\n";
293 return out;
296 std::ostream &CSharpTabCodeGen::FROM_STATE_ACTIONS()
298 out << "\t";
299 int totalStateNum = 0;
300 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
301 /* Write any eof action. */
302 FROM_STATE_ACTION(st);
303 if ( !st.last() ) {
304 out << ", ";
305 if ( ++totalStateNum % IALL == 0 )
306 out << "\n\t";
309 out << "\n";
310 return out;
313 std::ostream &CSharpTabCodeGen::EOF_ACTIONS()
315 out << "\t";
316 int totalStateNum = 0;
317 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
318 /* Write any eof action. */
319 EOF_ACTION(st);
320 if ( !st.last() ) {
321 out << ", ";
322 if ( ++totalStateNum % IALL == 0 )
323 out << "\n\t";
326 out << "\n";
327 return out;
330 std::ostream &CSharpTabCodeGen::EOF_TRANS()
332 out << "\t";
333 int totalStateNum = 0;
334 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
335 /* Write any eof action. */
336 long trans = 0;
337 if ( st->eofTrans != 0 ) {
338 assert( st->eofTrans->pos >= 0 );
339 trans = st->eofTrans->pos+1;
341 out << trans;
343 if ( !st.last() ) {
344 out << ", ";
345 if ( ++totalStateNum % IALL == 0 )
346 out << "\n\t";
349 out << "\n";
350 return out;
354 std::ostream &CSharpTabCodeGen::COND_KEYS()
356 out << '\t';
357 int totalTrans = 0;
358 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
359 /* Loop the state's transitions. */
360 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
361 /* Lower key. */
362 out << ALPHA_KEY( sc->lowKey ) << ", ";
363 if ( ++totalTrans % IALL == 0 )
364 out << "\n\t";
366 /* Upper key. */
367 out << ALPHA_KEY( sc->highKey ) << ", ";
368 if ( ++totalTrans % IALL == 0 )
369 out << "\n\t";
373 /* Output one last number so we don't have to figure out when the last
374 * entry is and avoid writing a comma. */
375 if ( keyOps->alphType->isChar )
376 out << "(char) " << 0 << "\n";
377 else
378 out << 0 << "\n";
380 return out;
383 std::ostream &CSharpTabCodeGen::COND_SPACES()
385 out << '\t';
386 int totalTrans = 0;
387 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
388 /* Loop the state's transitions. */
389 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
390 /* Cond Space id. */
391 out << sc->condSpace->condSpaceId << ", ";
392 if ( ++totalTrans % IALL == 0 )
393 out << "\n\t";
397 /* Output one last number so we don't have to figure out when the last
398 * entry is and avoid writing a comma. */
399 out << 0 << "\n";
400 return out;
403 std::ostream &CSharpTabCodeGen::KEYS()
405 out << '\t';
406 int totalTrans = 0;
407 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
408 /* Loop the singles. */
409 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
410 out << ALPHA_KEY( stel->lowKey ) << ", ";
411 if ( ++totalTrans % IALL == 0 )
412 out << "\n\t";
415 /* Loop the state's transitions. */
416 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
417 /* Lower key. */
418 out << ALPHA_KEY( rtel->lowKey ) << ", ";
419 if ( ++totalTrans % IALL == 0 )
420 out << "\n\t";
422 /* Upper key. */
423 out << ALPHA_KEY( rtel->highKey ) << ", ";
424 if ( ++totalTrans % IALL == 0 )
425 out << "\n\t";
429 /* Output one last number so we don't have to figure out when the last
430 * entry is and avoid writing a comma. */
431 if ( keyOps->alphType->isChar )
432 out << "(char) " << 0 << "\n";
433 else
434 out << 0 << "\n";
436 return out;
439 std::ostream &CSharpTabCodeGen::INDICIES()
441 int totalTrans = 0;
442 out << '\t';
443 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
444 /* Walk the singles. */
445 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
446 out << stel->value->id << ", ";
447 if ( ++totalTrans % IALL == 0 )
448 out << "\n\t";
451 /* Walk the ranges. */
452 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
453 out << rtel->value->id << ", ";
454 if ( ++totalTrans % IALL == 0 )
455 out << "\n\t";
458 /* The state's default index goes next. */
459 if ( st->defTrans != 0 ) {
460 out << st->defTrans->id << ", ";
461 if ( ++totalTrans % IALL == 0 )
462 out << "\n\t";
466 /* Output one last number so we don't have to figure out when the last
467 * entry is and avoid writing a comma. */
468 out << 0 << "\n";
469 return out;
472 std::ostream &CSharpTabCodeGen::TRANS_TARGS()
474 int totalTrans = 0;
475 out << '\t';
476 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
477 /* Walk the singles. */
478 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
479 RedTransAp *trans = stel->value;
480 out << trans->targ->id << ", ";
481 if ( ++totalTrans % IALL == 0 )
482 out << "\n\t";
485 /* Walk the ranges. */
486 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
487 RedTransAp *trans = rtel->value;
488 out << trans->targ->id << ", ";
489 if ( ++totalTrans % IALL == 0 )
490 out << "\n\t";
493 /* The state's default target state. */
494 if ( st->defTrans != 0 ) {
495 RedTransAp *trans = st->defTrans;
496 out << trans->targ->id << ", ";
497 if ( ++totalTrans % IALL == 0 )
498 out << "\n\t";
502 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
503 if ( st->eofTrans != 0 ) {
504 RedTransAp *trans = st->eofTrans;
505 trans->pos = totalTrans;
506 out << trans->targ->id << ", ";
507 if ( ++totalTrans % IALL == 0 )
508 out << "\n\t";
513 /* Output one last number so we don't have to figure out when the last
514 * entry is and avoid writing a comma. */
515 out << 0 << "\n";
516 return out;
520 std::ostream &CSharpTabCodeGen::TRANS_ACTIONS()
522 int totalTrans = 0;
523 out << '\t';
524 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
525 /* Walk the singles. */
526 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
527 RedTransAp *trans = stel->value;
528 TRANS_ACTION( trans ) << ", ";
529 if ( ++totalTrans % IALL == 0 )
530 out << "\n\t";
533 /* Walk the ranges. */
534 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
535 RedTransAp *trans = rtel->value;
536 TRANS_ACTION( trans ) << ", ";
537 if ( ++totalTrans % IALL == 0 )
538 out << "\n\t";
541 /* The state's default index goes next. */
542 if ( st->defTrans != 0 ) {
543 RedTransAp *trans = st->defTrans;
544 TRANS_ACTION( trans ) << ", ";
545 if ( ++totalTrans % IALL == 0 )
546 out << "\n\t";
550 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
551 if ( st->eofTrans != 0 ) {
552 RedTransAp *trans = st->eofTrans;
553 TRANS_ACTION( trans ) << ", ";
554 if ( ++totalTrans % IALL == 0 )
555 out << "\n\t";
559 /* Output one last number so we don't have to figure out when the last
560 * entry is and avoid writing a comma. */
561 out << 0 << "\n";
562 return out;
565 std::ostream &CSharpTabCodeGen::TRANS_TARGS_WI()
567 /* Transitions must be written ordered by their id. */
568 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
569 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
570 transPtrs[trans->id] = trans;
572 /* Keep a count of the num of items in the array written. */
573 out << '\t';
574 int totalStates = 0;
575 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
576 /* Record the position, need this for eofTrans. */
577 RedTransAp *trans = transPtrs[t];
578 trans->pos = t;
580 /* Write out the target state. */
581 out << trans->targ->id;
582 if ( t < redFsm->transSet.length()-1 ) {
583 out << ", ";
584 if ( ++totalStates % IALL == 0 )
585 out << "\n\t";
588 out << "\n";
589 delete[] transPtrs;
590 return out;
594 std::ostream &CSharpTabCodeGen::TRANS_ACTIONS_WI()
596 /* Transitions must be written ordered by their id. */
597 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
598 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
599 transPtrs[trans->id] = trans;
601 /* Keep a count of the num of items in the array written. */
602 out << '\t';
603 int totalAct = 0;
604 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
605 /* Write the function for the transition. */
606 RedTransAp *trans = transPtrs[t];
607 TRANS_ACTION( trans );
608 if ( t < redFsm->transSet.length()-1 ) {
609 out << ", ";
610 if ( ++totalAct % IALL == 0 )
611 out << "\n\t";
614 out << "\n";
615 delete[] transPtrs;
616 return out;
619 void CSharpTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
621 ret << "{" << vCS() << " = " << gotoDest << "; " <<
622 CTRL_FLOW() << "goto _again;}";
625 void CSharpTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
627 ret << "{" << vCS() << " = (";
628 INLINE_LIST( ret, ilItem->children, 0, inFinish );
629 ret << "); " << CTRL_FLOW() << "goto _again;}";
632 void CSharpTabCodeGen::CURS( ostream &ret, bool inFinish )
634 ret << "(_ps)";
637 void CSharpTabCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
639 ret << "(" << vCS() << ")";
642 void CSharpTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
644 ret << vCS() << " = " << nextDest << ";";
647 void CSharpTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
649 ret << vCS() << " = (";
650 INLINE_LIST( ret, ilItem->children, 0, inFinish );
651 ret << ");";
654 void CSharpTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
656 if ( prePushExpr != 0 ) {
657 ret << "{";
658 INLINE_LIST( ret, prePushExpr, 0, false );
661 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " <<
662 callDest << "; " << CTRL_FLOW() << "goto _again;}";
664 if ( prePushExpr != 0 )
665 ret << "}";
668 void CSharpTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
670 if ( prePushExpr != 0 ) {
671 ret << "{";
672 INLINE_LIST( ret, prePushExpr, 0, false );
675 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
676 INLINE_LIST( ret, ilItem->children, targState, inFinish );
677 ret << "); " << CTRL_FLOW() << "goto _again;}";
679 if ( prePushExpr != 0 )
680 ret << "}";
683 void CSharpTabCodeGen::RET( ostream &ret, bool inFinish )
685 ret << "{" << vCS() << " = " << STACK() << "[--" <<
686 TOP() << "]; ";
688 if ( postPopExpr != 0 ) {
689 ret << "{";
690 INLINE_LIST( ret, postPopExpr, 0, false );
691 ret << "}";
694 ret << CTRL_FLOW() << "goto _again;}";
697 void CSharpTabCodeGen::BREAK( ostream &ret, int targState )
699 outLabelUsed = true;
700 ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }";
703 void CSharpTabCodeGen::writeData()
705 /* If there are any transtion functions then output the array. If there
706 * are none, don't bother emitting an empty array that won't be used. */
707 if ( redFsm->anyActions() ) {
708 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
709 ACTIONS_ARRAY();
710 CLOSE_ARRAY() <<
711 "\n";
714 if ( redFsm->anyConditions() ) {
715 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
716 COND_OFFSETS();
717 CLOSE_ARRAY() <<
718 "\n";
720 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
721 COND_LENS();
722 CLOSE_ARRAY() <<
723 "\n";
725 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
726 COND_KEYS();
727 CLOSE_ARRAY() <<
728 "\n";
730 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
731 COND_SPACES();
732 CLOSE_ARRAY() <<
733 "\n";
736 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
737 KEY_OFFSETS();
738 CLOSE_ARRAY() <<
739 "\n";
741 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
742 KEYS();
743 CLOSE_ARRAY() <<
744 "\n";
746 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
747 SINGLE_LENS();
748 CLOSE_ARRAY() <<
749 "\n";
751 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
752 RANGE_LENS();
753 CLOSE_ARRAY() <<
754 "\n";
756 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
757 INDEX_OFFSETS();
758 CLOSE_ARRAY() <<
759 "\n";
761 if ( useIndicies ) {
762 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
763 INDICIES();
764 CLOSE_ARRAY() <<
765 "\n";
767 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
768 TRANS_TARGS_WI();
769 CLOSE_ARRAY() <<
770 "\n";
772 if ( redFsm->anyActions() ) {
773 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
774 TRANS_ACTIONS_WI();
775 CLOSE_ARRAY() <<
776 "\n";
779 else {
780 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
781 TRANS_TARGS();
782 CLOSE_ARRAY() <<
783 "\n";
785 if ( redFsm->anyActions() ) {
786 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
787 TRANS_ACTIONS();
788 CLOSE_ARRAY() <<
789 "\n";
793 if ( redFsm->anyToStateActions() ) {
794 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
795 TO_STATE_ACTIONS();
796 CLOSE_ARRAY() <<
797 "\n";
800 if ( redFsm->anyFromStateActions() ) {
801 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
802 FROM_STATE_ACTIONS();
803 CLOSE_ARRAY() <<
804 "\n";
807 if ( redFsm->anyEofActions() ) {
808 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
809 EOF_ACTIONS();
810 CLOSE_ARRAY() <<
811 "\n";
814 if ( redFsm->anyEofTrans() ) {
815 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
816 EOF_TRANS();
817 CLOSE_ARRAY() <<
818 "\n";
821 STATE_IDS();
824 void CSharpTabCodeGen::LOCATE_TRANS()
826 out <<
827 " _keys = " << KO() + "[" + vCS() + "]" << ";\n"
828 " _trans = " << CAST(transType) << IO() << "[" << vCS() << "];\n"
829 "\n"
830 " _klen = " << SL() << "[" << vCS() << "];\n"
831 " if ( _klen > 0 ) {\n"
832 " " << signedKeysType << " _lower = _keys;\n"
833 " " << signedKeysType << " _mid;\n"
834 " " << signedKeysType << " _upper = " << CAST(signedKeysType) <<
835 " (_keys + _klen - 1);\n"
836 " while (true) {\n"
837 " if ( _upper < _lower )\n"
838 " break;\n"
839 "\n"
840 " _mid = " << CAST(signedKeysType) <<
841 " (_lower + ((_upper-_lower) >> 1));\n"
842 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
843 " _upper = " << CAST(signedKeysType) << " (_mid - 1);\n"
844 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
845 " _lower = " << CAST(signedKeysType) << " (_mid + 1);\n"
846 " else {\n"
847 " _trans += " << CAST(transType) << " (_mid - _keys);\n"
848 " goto _match;\n"
849 " }\n"
850 " }\n"
851 " _keys += " << CAST(keysType) << " _klen;\n"
852 " _trans += " << CAST(transType) << " _klen;\n"
853 " }\n"
854 "\n"
855 " _klen = " << RL() << "[" << vCS() << "];\n"
856 " if ( _klen > 0 ) {\n"
857 " " << signedKeysType << " _lower = _keys;\n"
858 " " << signedKeysType << " _mid;\n"
859 " " << signedKeysType << " _upper = " << CAST(signedKeysType) <<
860 " (_keys + (_klen<<1) - 2);\n"
861 " while (true) {\n"
862 " if ( _upper < _lower )\n"
863 " break;\n"
864 "\n"
865 " _mid = " << CAST(signedKeysType) <<
866 " (_lower + (((_upper-_lower) >> 1) & ~1));\n"
867 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
868 " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n"
869 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
870 " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n"
871 " else {\n"
872 " _trans += " << CAST(transType) << "((_mid - _keys)>>1);\n"
873 " goto _match;\n"
874 " }\n"
875 " }\n"
876 " _trans += " << CAST(transType) << " _klen;\n"
877 " }\n"
878 "\n";
881 void CSharpTabCodeGen::COND_TRANSLATE()
883 out <<
884 " _widec = " << GET_KEY() << ";\n"
885 " _klen = " << CL() << "[" << vCS() << "];\n"
886 " _keys = " << CAST(keysType) << " ("<< CO() << "[" << vCS() << "]*2);\n"
887 " if ( _klen > 0 ) {\n"
888 " " << signedKeysType << " _lower = _keys;\n"
889 " " << signedKeysType << " _mid;\n"
890 " " << signedKeysType << " _upper = " << CAST(signedKeysType) <<
891 " (_keys + (_klen<<1) - 2);\n"
892 " while (true) {\n"
893 " if ( _upper < _lower )\n"
894 " break;\n"
895 "\n"
896 " _mid = " << CAST(signedKeysType) <<
897 " (_lower + (((_upper-_lower) >> 1) & ~1));\n"
898 " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
899 " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n"
900 " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
901 " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n"
902 " else {\n"
903 " switch ( " << C() << "[" << CO() << "[" << vCS() << "]"
904 " + ((_mid - _keys)>>1)] ) {\n";
906 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
907 GenCondSpace *condSpace = csi;
908 out << " case " << condSpace->condSpaceId << ": {\n";
909 out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
910 KEY(condSpace->baseKey) << " + (" << GET_KEY() <<
911 " - " << KEY(keyOps->minKey) << "));\n";
913 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
914 out << TABS(2) << "if ( ";
915 CONDITION( out, *csi );
916 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
917 out << " ) _widec += " << condValOffset << ";\n";
920 out <<
921 " break;\n"
922 " }\n";
925 SWITCH_DEFAULT();
927 out <<
928 " }\n"
929 " break;\n"
930 " }\n"
931 " }\n"
932 " }\n"
933 "\n";
936 void CSharpTabCodeGen::writeExec()
938 testEofUsed = false;
939 outLabelUsed = false;
940 initVarTypes();
942 out <<
943 " {\n"
944 " " << klenType << " _klen";
946 if ( redFsm->anyRegCurStateRef() )
947 out << ", _ps";
949 out <<
950 ";\n"
951 " " << transType << " _trans;\n";
953 if ( redFsm->anyConditions() )
954 out << " " << WIDE_ALPH_TYPE() << " _widec;\n";
956 if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
957 || redFsm->anyFromStateActions() )
959 out <<
960 " int _acts;\n"
961 " int _nacts;\n";
964 out <<
965 " " << keysType << " _keys;\n"
966 "\n";
967 // " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
969 if ( !noEnd ) {
970 testEofUsed = true;
971 out <<
972 " if ( " << P() << " == " << PE() << " )\n"
973 " goto _test_eof;\n";
976 if ( redFsm->errState != 0 ) {
977 outLabelUsed = true;
978 out <<
979 " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
980 " goto _out;\n";
983 out << "_resume:\n";
985 if ( redFsm->anyFromStateActions() ) {
986 out <<
987 " _acts = " << FSA() << "[" + vCS() + "]" << ";\n"
988 " _nacts = " << A() << "[_acts++];\n"
989 " while ( _nacts-- > 0 ) {\n"
990 " switch ( " << A() << "[_acts++] ) {\n";
991 FROM_STATE_ACTION_SWITCH();
992 SWITCH_DEFAULT() <<
993 " }\n"
994 " }\n"
995 "\n";
998 if ( redFsm->anyConditions() )
999 COND_TRANSLATE();
1001 LOCATE_TRANS();
1003 out << "_match:\n";
1005 if ( useIndicies )
1006 out << " _trans = " << CAST(transType) << I() << "[_trans];\n";
1008 if ( redFsm->anyEofTrans() )
1009 out << "_eof_trans:\n";
1011 if ( redFsm->anyRegCurStateRef() )
1012 out << " _ps = " << vCS() << ";\n";
1014 out <<
1015 " " << vCS() << " = " << TT() << "[_trans];\n"
1016 "\n";
1018 if ( redFsm->anyRegActions() ) {
1019 out <<
1020 " if ( " << TA() << "[_trans] == 0 )\n"
1021 " goto _again;\n"
1022 "\n"
1023 " _acts = " << TA() << "[_trans]" << ";\n"
1024 " _nacts = " << A() << "[_acts++];\n"
1025 " while ( _nacts-- > 0 )\n {\n"
1026 " switch ( " << A() << "[_acts++] )\n {\n";
1027 ACTION_SWITCH();
1028 SWITCH_DEFAULT() <<
1029 " }\n"
1030 " }\n"
1031 "\n";
1034 if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
1035 redFsm->anyActionCalls() || redFsm->anyActionRets() )
1036 out << "_again:\n";
1038 if ( redFsm->anyToStateActions() ) {
1039 out <<
1040 " _acts = " << TSA() << "[" << vCS() << "]" << ";\n"
1041 " _nacts = " << A() << "[_acts++];\n"
1042 " while ( _nacts-- > 0 ) {\n"
1043 " switch ( " << A() << "[_acts++] ) {\n";
1044 TO_STATE_ACTION_SWITCH();
1045 SWITCH_DEFAULT() <<
1046 " }\n"
1047 " }\n"
1048 "\n";
1051 if ( redFsm->errState != 0 ) {
1052 outLabelUsed = true;
1053 out <<
1054 " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
1055 " goto _out;\n";
1058 if ( !noEnd ) {
1059 out <<
1060 " if ( ++" << P() << " != " << PE() << " )\n"
1061 " goto _resume;\n";
1063 else {
1064 out <<
1065 " " << P() << " += 1;\n"
1066 " goto _resume;\n";
1069 if ( testEofUsed )
1070 out << " _test_eof: {}\n";
1072 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
1073 out <<
1074 " if ( " << P() << " == " << vEOF() << " )\n"
1075 " {\n";
1077 if ( redFsm->anyEofTrans() ) {
1078 out <<
1079 " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
1080 " _trans = " << CAST(transType) << " (" << ET() <<
1081 "[" << vCS() << "] - 1);\n"
1082 " goto _eof_trans;\n"
1083 " }\n";
1086 if ( redFsm->anyEofActions() ) {
1087 out <<
1088 " int __acts = " <<
1089 EA() << "[" << vCS() << "]" << ";\n"
1090 " int __nacts = " <<
1091 A() << "[__acts++];\n"
1092 " while ( __nacts-- > 0 ) {\n"
1093 " switch ( " << A() << "[__acts++] ) {\n";
1094 EOF_ACTION_SWITCH();
1095 SWITCH_DEFAULT() <<
1096 " }\n"
1097 " }\n";
1100 out <<
1101 " }\n"
1102 "\n";
1105 if ( outLabelUsed )
1106 out << " _out: {}\n";
1108 out << " }\n";
1111 void CSharpTabCodeGen::initVarTypes()
1113 int klenMax = MAX(MAX(redFsm->maxCondLen, redFsm->maxRangeLen),
1114 redFsm->maxSingleLen);
1115 int keysMax = MAX(MAX(redFsm->maxKeyOffset, klenMax),
1116 redFsm->maxCondOffset);
1117 int transMax = MAX(MAX(redFsm->maxIndex+1, redFsm->maxIndexOffset), keysMax);
1118 transMax = MAX(transMax, klenMax);
1119 transType = ARRAY_TYPE(transMax);
1120 klenType = ARRAY_TYPE(klenMax);
1121 keysType = ARRAY_TYPE(keysMax);
1122 signedKeysType = ARRAY_TYPE(keysMax, true);