2 * Copyright 2006-2007 Adrian Thurston <thurston@complang.org>
3 * 2007 Colin Fleming <colin.fleming@caverock.com>
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
24 #include "javacodegen.h"
30 /* Integer array line length. */
33 /* Static array initialization item count
34 * (should be multiple of IALL). */
45 using std::ostringstream;
58 void javaLineDirective( ostream &out, const char *fileName, int line )
60 /* Write the preprocessor line info for to the input file. */
61 out << "// line " << line << " \"";
62 for ( const char *pc = fileName; *pc != 0; pc++ ) {
71 void JavaTabCodeGen::genLineDirective( ostream &out )
73 std::streambuf *sbuf = out.rdbuf();
74 output_filter *filter = static_cast<output_filter*>(sbuf);
75 javaLineDirective( out, filter->fileName, filter->line + 1 );
78 void JavaTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
80 ret << "{" << vCS() << " = " << gotoDest << "; _goto_targ = " << _again << "; " <<
81 CTRL_FLOW() << "continue _goto;}";
84 void JavaTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
86 ret << "{" << vCS() << " = (";
87 INLINE_LIST( ret, ilItem->children, 0, inFinish );
88 ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
91 void JavaTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
93 if ( prePushExpr != 0 ) {
95 INLINE_LIST( ret, prePushExpr, 0, false );
98 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " <<
99 callDest << "; _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
101 if ( prePushExpr != 0 )
105 void JavaTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
107 if ( prePushExpr != 0 ) {
109 INLINE_LIST( ret, prePushExpr, 0, false );
112 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
113 INLINE_LIST( ret, ilItem->children, targState, inFinish );
114 ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
116 if ( prePushExpr != 0 )
120 void JavaTabCodeGen::RET( ostream &ret, bool inFinish )
122 ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
124 if ( postPopExpr != 0 ) {
126 INLINE_LIST( ret, postPopExpr, 0, false );
130 ret << "_goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
133 void JavaTabCodeGen::BREAK( ostream &ret, int targState )
135 ret << "{ " << P() << " += 1; _goto_targ = " << _out << "; " <<
136 CTRL_FLOW() << " continue _goto;}";
139 void JavaTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
141 ret << vCS() << " = " << nextDest << ";";
144 void JavaTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
146 ret << vCS() << " = (";
147 INLINE_LIST( ret, ilItem->children, 0, inFinish );
151 void JavaTabCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
153 /* The parser gives fexec two children. The double brackets are for D
154 * code. If the inline list is a single word it will get interpreted as a
155 * C-style cast by the D compiler. */
156 ret << "{" << P() << " = ((";
157 INLINE_LIST( ret, item->children, targState, inFinish );
161 /* Write out an inline tree structure. Walks the list and possibly calls out
162 * to virtual functions than handle language specific items in the tree. */
163 void JavaTabCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList,
164 int targState, bool inFinish )
166 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
167 switch ( item->type ) {
168 case GenInlineItem::Text:
171 case GenInlineItem::Goto:
172 GOTO( ret, item->targState->id, inFinish );
174 case GenInlineItem::Call:
175 CALL( ret, item->targState->id, targState, inFinish );
177 case GenInlineItem::Next:
178 NEXT( ret, item->targState->id, inFinish );
180 case GenInlineItem::Ret:
181 RET( ret, inFinish );
183 case GenInlineItem::PChar:
186 case GenInlineItem::Char:
189 case GenInlineItem::Hold:
192 case GenInlineItem::Exec:
193 EXEC( ret, item, targState, inFinish );
195 case GenInlineItem::Curs:
198 case GenInlineItem::Targs:
199 ret << "(" << vCS() << ")";
201 case GenInlineItem::Entry:
202 ret << item->targState->id;
204 case GenInlineItem::GotoExpr:
205 GOTO_EXPR( ret, item, inFinish );
207 case GenInlineItem::CallExpr:
208 CALL_EXPR( ret, item, targState, inFinish );
210 case GenInlineItem::NextExpr:
211 NEXT_EXPR( ret, item, inFinish );
213 case GenInlineItem::LmSwitch:
214 LM_SWITCH( ret, item, targState, inFinish );
216 case GenInlineItem::LmSetActId:
217 SET_ACT( ret, item );
219 case GenInlineItem::LmSetTokEnd:
220 SET_TOKEND( ret, item );
222 case GenInlineItem::LmGetTokEnd:
223 GET_TOKEND( ret, item );
225 case GenInlineItem::LmInitTokStart:
226 INIT_TOKSTART( ret, item );
228 case GenInlineItem::LmInitAct:
229 INIT_ACT( ret, item );
231 case GenInlineItem::LmSetTokStart:
232 SET_TOKSTART( ret, item );
234 case GenInlineItem::SubAction:
235 SUB_ACTION( ret, item, targState, inFinish );
237 case GenInlineItem::Break:
238 BREAK( ret, targState );
244 string JavaTabCodeGen::DATA_PREFIX()
247 return FSM_NAME() + "_";
251 /* Emit the alphabet data type. */
252 string JavaTabCodeGen::ALPH_TYPE()
254 string ret = keyOps->alphType->data1;
255 if ( keyOps->alphType->data2 != 0 ) {
257 ret += + keyOps->alphType->data2;
262 /* Emit the alphabet data type. */
263 string JavaTabCodeGen::WIDE_ALPH_TYPE()
266 if ( redFsm->maxKey <= keyOps->maxKey )
269 long long maxKeyVal = redFsm->maxKey.getLongLong();
270 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
271 assert( wideType != 0 );
273 ret = wideType->data1;
274 if ( wideType->data2 != 0 ) {
276 ret += wideType->data2;
284 void JavaTabCodeGen::COND_TRANSLATE()
287 " _widec = " << GET_KEY() << ";\n"
288 " _keys = " << CO() << "[" << vCS() << "]*2\n;"
289 " _klen = " << CL() << "[" << vCS() << "];\n"
290 " if ( _klen > 0 ) {\n"
291 " int _lower = _keys\n;"
293 " int _upper = _keys + (_klen<<1) - 2;\n"
295 " if ( _upper < _lower )\n"
298 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
299 " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
300 " _upper = _mid - 2;\n"
301 " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
302 " _lower = _mid + 2;\n"
304 " switch ( " << C() << "[" << CO() << "[" << vCS() << "]"
305 " + ((_mid - _keys)>>1)] ) {\n"
308 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
309 GenCondSpace *condSpace = csi;
310 out << " case " << condSpace->condSpaceId << ": {\n";
311 out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) <<
312 " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n";
314 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
315 out << TABS(2) << "if ( ";
316 CONDITION( out, *csi );
317 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
318 out << " ) _widec += " << condValOffset << ";\n";
336 void JavaTabCodeGen::LOCATE_TRANS()
340 " _keys = " << KO() << "[" << vCS() << "]" << ";\n"
341 " _trans = " << IO() << "[" << vCS() << "];\n"
342 " _klen = " << SL() << "[" << vCS() << "];\n"
343 " if ( _klen > 0 ) {\n"
344 " int _lower = _keys;\n"
346 " int _upper = _keys + _klen - 1;\n"
348 " if ( _upper < _lower )\n"
351 " _mid = _lower + ((_upper-_lower) >> 1);\n"
352 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
353 " _upper = _mid - 1;\n"
354 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
355 " _lower = _mid + 1;\n"
357 " _trans += (_mid - _keys);\n"
362 " _trans += _klen;\n"
365 " _klen = " << RL() << "[" << vCS() << "];\n"
366 " if ( _klen > 0 ) {\n"
367 " int _lower = _keys;\n"
369 " int _upper = _keys + (_klen<<1) - 2;\n"
371 " if ( _upper < _lower )\n"
374 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
375 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
376 " _upper = _mid - 2;\n"
377 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
378 " _lower = _mid + 2;\n"
380 " _trans += ((_mid - _keys)>>1);\n"
384 " _trans += _klen;\n"
386 " } while (false);\n"
390 /* Determine if we should use indicies or not. */
391 void JavaTabCodeGen::calcIndexSize()
393 int sizeWithInds = 0, sizeWithoutInds = 0;
395 /* Calculate cost of using with indicies. */
396 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
397 int totalIndex = st->outSingle.length() + st->outRange.length() +
398 (st->defTrans == 0 ? 0 : 1);
399 sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
401 sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
402 if ( redFsm->anyActions() )
403 sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
405 /* Calculate the cost of not using indicies. */
406 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
407 int totalIndex = st->outSingle.length() + st->outRange.length() +
408 (st->defTrans == 0 ? 0 : 1);
409 sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
410 if ( redFsm->anyActions() )
411 sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
414 /* If using indicies reduces the size, use them. */
415 useIndicies = sizeWithInds < sizeWithoutInds;
418 int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
421 if ( state->toStateAction != 0 )
422 act = state->toStateAction->location+1;
426 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
429 if ( state->fromStateAction != 0 )
430 act = state->fromStateAction->location+1;
434 int JavaTabCodeGen::EOF_ACTION( RedStateAp *state )
437 if ( state->eofAction != 0 )
438 act = state->eofAction->location+1;
443 int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans )
445 /* If there are actions, emit them. Otherwise emit zero. */
447 if ( trans->action != 0 )
448 act = trans->action->location+1;
452 std::ostream &JavaTabCodeGen::TO_STATE_ACTION_SWITCH()
454 /* Walk the list of functions, printing the cases. */
455 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
456 /* Write out referenced actions. */
457 if ( act->numToStateRefs > 0 ) {
458 /* Write the case label, the action and the case break. */
459 out << "\tcase " << act->actionId << ":\n";
460 ACTION( out, act, 0, false );
465 genLineDirective( out );
469 std::ostream &JavaTabCodeGen::FROM_STATE_ACTION_SWITCH()
471 /* Walk the list of functions, printing the cases. */
472 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
473 /* Write out referenced actions. */
474 if ( act->numFromStateRefs > 0 ) {
475 /* Write the case label, the action and the case break. */
476 out << "\tcase " << act->actionId << ":\n";
477 ACTION( out, act, 0, false );
482 genLineDirective( out );
486 std::ostream &JavaTabCodeGen::EOF_ACTION_SWITCH()
488 /* Walk the list of functions, printing the cases. */
489 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
490 /* Write out referenced actions. */
491 if ( act->numEofRefs > 0 ) {
492 /* Write the case label, the action and the case break. */
493 out << "\tcase " << act->actionId << ":\n";
494 ACTION( out, act, 0, true );
499 genLineDirective( out );
504 std::ostream &JavaTabCodeGen::ACTION_SWITCH()
506 /* Walk the list of functions, printing the cases. */
507 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
508 /* Write out referenced actions. */
509 if ( act->numTransRefs > 0 ) {
510 /* Write the case label, the action and the case break. */
511 out << "\tcase " << act->actionId << ":\n";
512 ACTION( out, act, 0, false );
517 genLineDirective( out );
521 std::ostream &JavaTabCodeGen::COND_OFFSETS()
523 int curKeyOffset = 0;
524 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
525 /* Write the key offset. */
526 ARRAY_ITEM( INT(curKeyOffset), st.last() );
528 /* Move the key offset ahead. */
529 curKeyOffset += st->stateCondList.length();
534 std::ostream &JavaTabCodeGen::KEY_OFFSETS()
536 int curKeyOffset = 0;
537 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
538 /* Write the key offset. */
539 ARRAY_ITEM( INT(curKeyOffset), st.last() );
541 /* Move the key offset ahead. */
542 curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
548 std::ostream &JavaTabCodeGen::INDEX_OFFSETS()
550 int curIndOffset = 0;
551 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
552 /* Write the index offset. */
553 ARRAY_ITEM( INT(curIndOffset), st.last() );
555 /* Move the index offset ahead. */
556 curIndOffset += st->outSingle.length() + st->outRange.length();
557 if ( st->defTrans != 0 )
563 std::ostream &JavaTabCodeGen::COND_LENS()
565 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
566 /* Write singles length. */
567 ARRAY_ITEM( INT(st->stateCondList.length()), st.last() );
573 std::ostream &JavaTabCodeGen::SINGLE_LENS()
575 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
576 /* Write singles length. */
577 ARRAY_ITEM( INT(st->outSingle.length()), st.last() );
582 std::ostream &JavaTabCodeGen::RANGE_LENS()
584 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
585 /* Emit length of range index. */
586 ARRAY_ITEM( INT(st->outRange.length()), st.last() );
591 std::ostream &JavaTabCodeGen::TO_STATE_ACTIONS()
593 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
594 /* Write any eof action. */
595 ARRAY_ITEM( INT(TO_STATE_ACTION(st)), st.last() );
600 std::ostream &JavaTabCodeGen::FROM_STATE_ACTIONS()
602 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
603 /* Write any eof action. */
604 ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), st.last() );
609 std::ostream &JavaTabCodeGen::EOF_ACTIONS()
611 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
612 /* Write any eof action. */
613 ARRAY_ITEM( INT(EOF_ACTION(st)), st.last() );
618 std::ostream &JavaTabCodeGen::EOF_TRANS()
620 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
621 /* Write any eof action. */
623 if ( st->eofTrans != 0 ) {
624 assert( st->eofTrans->pos >= 0 );
625 trans = st->eofTrans->pos+1;
628 /* Write any eof action. */
629 ARRAY_ITEM( INT(trans), st.last() );
635 std::ostream &JavaTabCodeGen::COND_KEYS()
637 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
638 /* Loop the state's transitions. */
639 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
641 ARRAY_ITEM( KEY( sc->lowKey ), false );
642 ARRAY_ITEM( KEY( sc->highKey ), false );
646 /* Output one last number so we don't have to figure out when the last
647 * entry is and avoid writing a comma. */
648 ARRAY_ITEM( INT(0), true );
652 std::ostream &JavaTabCodeGen::COND_SPACES()
654 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
655 /* Loop the state's transitions. */
656 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
658 ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), false );
662 /* Output one last number so we don't have to figure out when the last
663 * entry is and avoid writing a comma. */
664 ARRAY_ITEM( INT(0), true );
668 std::ostream &JavaTabCodeGen::KEYS()
670 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
671 /* Loop the singles. */
672 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
673 ARRAY_ITEM( KEY( stel->lowKey ), false );
676 /* Loop the state's transitions. */
677 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
679 ARRAY_ITEM( KEY( rtel->lowKey ), false );
682 ARRAY_ITEM( KEY( rtel->highKey ), false );
686 /* Output one last number so we don't have to figure out when the last
687 * entry is and avoid writing a comma. */
688 ARRAY_ITEM( INT(0), true );
692 std::ostream &JavaTabCodeGen::INDICIES()
694 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
695 /* Walk the singles. */
696 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
697 ARRAY_ITEM( KEY( stel->value->id ), false );
700 /* Walk the ranges. */
701 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
702 ARRAY_ITEM( KEY( rtel->value->id ), false );
705 /* The state's default index goes next. */
706 if ( st->defTrans != 0 ) {
707 ARRAY_ITEM( KEY( st->defTrans->id ), false );
711 /* Output one last number so we don't have to figure out when the last
712 * entry is and avoid writing a comma. */
713 ARRAY_ITEM( INT(0), true );
717 std::ostream &JavaTabCodeGen::TRANS_TARGS()
720 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
721 /* Walk the singles. */
722 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
723 RedTransAp *trans = stel->value;
724 ARRAY_ITEM( KEY( trans->targ->id ), false );
728 /* Walk the ranges. */
729 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
730 RedTransAp *trans = rtel->value;
731 ARRAY_ITEM( KEY( trans->targ->id ), false );
735 /* The state's default target state. */
736 if ( st->defTrans != 0 ) {
737 RedTransAp *trans = st->defTrans;
738 ARRAY_ITEM( KEY( trans->targ->id ), false );
743 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
744 if ( st->eofTrans != 0 ) {
745 RedTransAp *trans = st->eofTrans;
746 trans->pos = totalTrans++;
747 ARRAY_ITEM( KEY( trans->targ->id ), false );
751 /* Output one last number so we don't have to figure out when the last
752 * entry is and avoid writing a comma. */
753 ARRAY_ITEM( INT(0), true );
758 std::ostream &JavaTabCodeGen::TRANS_ACTIONS()
760 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
761 /* Walk the singles. */
762 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
763 RedTransAp *trans = stel->value;
764 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
767 /* Walk the ranges. */
768 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
769 RedTransAp *trans = rtel->value;
770 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
773 /* The state's default index goes next. */
774 if ( st->defTrans != 0 ) {
775 RedTransAp *trans = st->defTrans;
776 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
780 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
781 if ( st->eofTrans != 0 ) {
782 RedTransAp *trans = st->eofTrans;
783 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
787 /* Output one last number so we don't have to figure out when the last
788 * entry is and avoid writing a comma. */
789 ARRAY_ITEM( INT(0), true );
793 std::ostream &JavaTabCodeGen::TRANS_TARGS_WI()
795 /* Transitions must be written ordered by their id. */
796 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
797 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
798 transPtrs[trans->id] = trans;
800 /* Keep a count of the num of items in the array written. */
801 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
802 /* Save the position. Needed for eofTargs. */
803 RedTransAp *trans = transPtrs[t];
806 /* Write out the target state. */
807 ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) );
814 std::ostream &JavaTabCodeGen::TRANS_ACTIONS_WI()
816 /* Transitions must be written ordered by their id. */
817 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
818 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
819 transPtrs[trans->id] = trans;
821 /* Keep a count of the num of items in the array written. */
822 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
823 /* Write the function for the transition. */
824 RedTransAp *trans = transPtrs[t];
825 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ( t >= redFsm->transSet.length()-1 ) );
831 void JavaTabCodeGen::writeExports()
833 if ( exportList.length() > 0 ) {
834 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
835 STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name )
836 << " = " << KEY(ex->key) << ";\n";
842 void JavaTabCodeGen::writeStart()
844 out << START_STATE_ID();
847 void JavaTabCodeGen::writeFirstFinal()
849 out << FIRST_FINAL_STATE();
852 void JavaTabCodeGen::writeError()
854 out << ERROR_STATE();
857 void JavaTabCodeGen::writeData()
859 /* If there are any transtion functions then output the array. If there
860 * are none, don't bother emitting an empty array that won't be used. */
861 if ( redFsm->anyActions() ) {
862 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
868 if ( redFsm->anyConditions() ) {
869 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
874 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
879 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
884 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
890 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
895 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
900 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
905 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
910 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
916 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
921 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
926 if ( redFsm->anyActions() ) {
927 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
934 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
939 if ( redFsm->anyActions() ) {
940 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
947 if ( redFsm->anyToStateActions() ) {
948 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
954 if ( redFsm->anyFromStateActions() ) {
955 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
956 FROM_STATE_ACTIONS();
961 if ( redFsm->anyEofActions() ) {
962 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
968 if ( redFsm->anyEofTrans() ) {
969 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
975 if ( redFsm->startState != 0 )
976 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
979 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
982 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
986 if ( entryPointNames.length() > 0 ) {
987 for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
988 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) <<
989 " = " << entryPointIds[en.pos()] << ";\n";
995 void JavaTabCodeGen::writeExec()
1001 if ( redFsm->anyRegCurStateRef() )
1006 " int _trans = 0;\n";
1008 if ( redFsm->anyConditions() )
1009 out << " int _widec;\n";
1011 if ( redFsm->anyToStateActions() || redFsm->anyRegActions() ||
1012 redFsm->anyFromStateActions() )
1021 " int _goto_targ = 0;\n"
1025 " _goto: while (true) {\n"
1026 " switch ( _goto_targ ) {\n"
1031 " if ( " << P() << " == " << PE() << " ) {\n"
1032 " _goto_targ = " << _test_eof << ";\n"
1033 " continue _goto;\n"
1037 if ( redFsm->errState != 0 ) {
1039 " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
1040 " _goto_targ = " << _out << ";\n"
1041 " continue _goto;\n"
1045 out << "case " << _resume << ":\n";
1047 if ( redFsm->anyFromStateActions() ) {
1049 " _acts = " << FSA() << "[" << vCS() << "]" << ";\n"
1050 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1051 " while ( _nacts-- > 0 ) {\n"
1052 " switch ( " << A() << "[_acts++] ) {\n";
1053 FROM_STATE_ACTION_SWITCH() <<
1059 if ( redFsm->anyConditions() )
1065 out << " _trans = " << I() << "[_trans];\n";
1067 if ( redFsm->anyEofTrans() )
1068 out << "case " << _eof_trans << ":\n";
1070 if ( redFsm->anyRegCurStateRef() )
1071 out << " _ps = " << vCS() << ";\n";
1074 " " << vCS() << " = " << TT() << "[_trans];\n"
1077 if ( redFsm->anyRegActions() ) {
1079 " if ( " << TA() << "[_trans] != 0 ) {\n"
1080 " _acts = " << TA() << "[_trans]" << ";\n"
1081 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1082 " while ( _nacts-- > 0 )\n {\n"
1083 " switch ( " << A() << "[_acts++] )\n"
1092 out << "case " << _again << ":\n";
1094 if ( redFsm->anyToStateActions() ) {
1096 " _acts = " << TSA() << "[" << vCS() << "]" << ";\n"
1097 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1098 " while ( _nacts-- > 0 ) {\n"
1099 " switch ( " << A() << "[_acts++] ) {\n";
1100 TO_STATE_ACTION_SWITCH() <<
1106 if ( redFsm->errState != 0 ) {
1108 " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
1109 " _goto_targ = " << _out << ";\n"
1110 " continue _goto;\n"
1116 " if ( ++" << P() << " != " << PE() << " ) {\n"
1117 " _goto_targ = " << _resume << ";\n"
1118 " continue _goto;\n"
1123 " " << P() << " += 1;\n"
1124 " _goto_targ = " << _resume << ";\n"
1125 " continue _goto;\n";
1128 out << "case " << _test_eof << ":\n";
1130 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
1132 " if ( " << P() << " == " << vEOF() << " )\n"
1135 if ( redFsm->anyEofTrans() ) {
1137 " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
1138 " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
1139 " _goto_targ = " << _eof_trans << ";\n"
1140 " continue _goto;\n"
1144 if ( redFsm->anyEofActions() ) {
1146 " int __acts = " << EA() << "[" << vCS() << "]" << ";\n"
1147 " int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n"
1148 " while ( __nacts-- > 0 ) {\n"
1149 " switch ( " << A() << "[__acts++] ) {\n";
1150 EOF_ACTION_SWITCH() <<
1160 out << "case " << _out << ":\n";
1162 /* The switch and goto loop. */
1164 out << " break; }\n";
1166 /* The execute block. */
1170 std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name )
1177 out << "private static " << type << "[] init_" << name << "_0()\n"
1179 "return new " << type << " [] {\n\t";
1183 std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last )
1187 out << setw(5) << setiosflags(ios::right) << item;
1190 if ( item_count % SAIIC == 0 ) {
1191 out << "\n\t};\n};\n"
1192 "private static "<< array_type << "[] init_" <<
1193 array_name << "_" << div_count << "()\n"
1195 "return new " << array_type << " [] {\n\t";
1197 } else if (item_count % IALL == 0) {
1206 std::ostream &JavaTabCodeGen::CLOSE_ARRAY()
1208 out << "\n\t};\n}\n\n";
1210 if (item_count < SAIIC) {
1211 out << "private static final " << array_type << " " << array_name <<
1212 "[] = init_" << array_name << "_0();\n\n";
1214 out << "private static final " << array_type << " [] combine_" << array_name
1216 << array_type << " [] combined = new " << array_type <<
1217 " [ " << item_count << " ];\n\t";
1219 int full_blocks = item_count / SAIIC;
1220 for (;block < full_blocks; ++block) {
1221 out << "System.arraycopy ( init_" << array_name << "_" << block <<
1222 "(), 0, combined, " << SAIIC * block << ", " << SAIIC << " );\n\t";
1224 if ( (item_count % SAIIC) > 0 ) {
1225 out << "System.arraycopy ( init_" << array_name << "_" << block <<
1226 "(), 0, combined, " << SAIIC * block << ", " <<
1227 (item_count % SAIIC) << " );\n\t";
1229 out << "return combined;\n}\n";
1230 out << "private static final " << array_type << " [] " << array_name <<
1231 " = combine_" << array_name << "();";
1237 std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name )
1239 out << "static final " << type << " " << name;
1243 string JavaTabCodeGen::ARR_OFF( string ptr, string offset )
1245 return ptr + " + " + offset;
1248 string JavaTabCodeGen::CAST( string type )
1250 return "(" + type + ")";
1253 string JavaTabCodeGen::NULL_ITEM()
1255 /* In java we use integers instead of pointers. */
1259 string JavaTabCodeGen::GET_KEY()
1262 if ( getKeyExpr != 0 ) {
1263 /* Emit the user supplied method of retrieving the key. */
1265 INLINE_LIST( ret, getKeyExpr, 0, false );
1269 /* Expression for retrieving the key, use simple dereference. */
1270 ret << DATA() << "[" << P() << "]";
1275 string JavaTabCodeGen::CTRL_FLOW()
1277 return "if (true) ";
1280 unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal )
1282 long long maxValLL = (long long) maxVal;
1283 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1284 assert( arrayType != 0 );
1285 return arrayType->size;
1288 string JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal )
1290 long long maxValLL = (long long) maxVal;
1291 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1292 assert( arrayType != 0 );
1294 string ret = arrayType->data1;
1295 if ( arrayType->data2 != 0 ) {
1297 ret += arrayType->data2;
1303 /* Write out the fsm name. */
1304 string JavaTabCodeGen::FSM_NAME()
1309 /* Emit the offset of the start state as a decimal integer. */
1310 string JavaTabCodeGen::START_STATE_ID()
1313 ret << redFsm->startState->id;
1317 /* Write out the array of actions. */
1318 std::ostream &JavaTabCodeGen::ACTIONS_ARRAY()
1320 ARRAY_ITEM( INT(0), false );
1321 for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
1322 /* Write out the length, which will never be the last character. */
1323 ARRAY_ITEM( INT(act->key.length()), false );
1325 for ( GenActionTable::Iter item = act->key; item.lte(); item++ )
1326 ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) );
1332 string JavaTabCodeGen::ACCESS()
1335 if ( accessExpr != 0 )
1336 INLINE_LIST( ret, accessExpr, 0, false );
1340 string JavaTabCodeGen::P()
1347 INLINE_LIST( ret, pExpr, 0, false );
1353 string JavaTabCodeGen::PE()
1360 INLINE_LIST( ret, peExpr, 0, false );
1366 string JavaTabCodeGen::vEOF()
1373 INLINE_LIST( ret, eofExpr, 0, false );
1379 string JavaTabCodeGen::vCS()
1383 ret << ACCESS() << "cs";
1385 /* Emit the user supplied method of retrieving the key. */
1387 INLINE_LIST( ret, csExpr, 0, false );
1393 string JavaTabCodeGen::TOP()
1397 ret << ACCESS() + "top";
1400 INLINE_LIST( ret, topExpr, 0, false );
1406 string JavaTabCodeGen::STACK()
1409 if ( stackExpr == 0 )
1410 ret << ACCESS() + "stack";
1413 INLINE_LIST( ret, stackExpr, 0, false );
1419 string JavaTabCodeGen::ACT()
1423 ret << ACCESS() + "act";
1426 INLINE_LIST( ret, actExpr, 0, false );
1432 string JavaTabCodeGen::TOKSTART()
1435 if ( tokstartExpr == 0 )
1436 ret << ACCESS() + "ts";
1439 INLINE_LIST( ret, tokstartExpr, 0, false );
1445 string JavaTabCodeGen::TOKEND()
1448 if ( tokendExpr == 0 )
1449 ret << ACCESS() + "te";
1452 INLINE_LIST( ret, tokendExpr, 0, false );
1458 string JavaTabCodeGen::DATA()
1461 if ( dataExpr == 0 )
1462 ret << ACCESS() + "data";
1465 INLINE_LIST( ret, dataExpr, 0, false );
1472 string JavaTabCodeGen::GET_WIDE_KEY()
1474 if ( redFsm->anyConditions() )
1480 string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state )
1482 if ( state->stateCondList.length() > 0 )
1488 /* Write out level number of tabs. Makes the nested binary search nice
1490 string JavaTabCodeGen::TABS( int level )
1493 while ( level-- > 0 )
1498 string JavaTabCodeGen::KEY( Key key )
1501 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
1502 ret << key.getVal();
1504 ret << (unsigned long) key.getVal();
1508 string JavaTabCodeGen::INT( int i )
1515 void JavaTabCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item,
1516 int targState, int inFinish )
1519 " switch( " << ACT() << " ) {\n";
1521 for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
1522 /* Write the case label, the action and the case break. */
1523 if ( lma->lmId < 0 )
1524 ret << " default:\n";
1526 ret << " case " << lma->lmId << ":\n";
1528 /* Write the block and close it off. */
1530 INLINE_LIST( ret, lma->children, targState, inFinish );
1541 void JavaTabCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
1543 ret << ACT() << " = " << item->lmId << ";";
1546 void JavaTabCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
1548 /* The tokend action sets tokend. */
1549 ret << TOKEND() << " = " << P();
1550 if ( item->offset != 0 )
1551 out << "+" << item->offset;
1555 void JavaTabCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
1560 void JavaTabCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
1562 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
1565 void JavaTabCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
1567 ret << ACT() << " = 0;";
1570 void JavaTabCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
1572 ret << TOKSTART() << " = " << P() << ";";
1575 void JavaTabCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
1576 int targState, bool inFinish )
1578 if ( item->children->length() > 0 ) {
1579 /* Write the block and close it off. */
1581 INLINE_LIST( ret, item->children, targState, inFinish );
1586 void JavaTabCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish )
1588 /* Write the preprocessor line info for going into the source file. */
1589 javaLineDirective( ret, action->loc.fileName, action->loc.line );
1591 /* Write the block and close it off. */
1593 INLINE_LIST( ret, action->inlineList, targState, inFinish );
1597 void JavaTabCodeGen::CONDITION( ostream &ret, GenAction *condition )
1600 javaLineDirective( ret, condition->loc.fileName, condition->loc.line );
1601 INLINE_LIST( ret, condition->inlineList, 0, false );
1604 string JavaTabCodeGen::ERROR_STATE()
1607 if ( redFsm->errState != 0 )
1608 ret << redFsm->errState->id;
1614 string JavaTabCodeGen::FIRST_FINAL_STATE()
1617 if ( redFsm->firstFinState != 0 )
1618 ret << redFsm->firstFinState->id;
1620 ret << redFsm->nextStateId;
1624 void JavaTabCodeGen::writeInit()
1629 out << "\t" << vCS() << " = " << START() << ";\n";
1631 /* If there are any calls, then the stack top needs initialization. */
1632 if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
1633 out << "\t" << TOP() << " = 0;\n";
1635 if ( hasLongestMatch ) {
1637 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
1638 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
1639 " " << ACT() << " = 0;\n";
1644 void JavaTabCodeGen::finishRagelDef()
1646 /* The frontend will do this for us, but it may be a good idea to force it
1647 * if the intermediate file is edited. */
1648 redFsm->sortByStateId();
1650 /* Choose default transitions and the single transition. */
1651 redFsm->chooseDefaultSpan();
1653 /* Maybe do flat expand, otherwise choose single. */
1654 redFsm->chooseSingle();
1656 /* If any errors have occured in the input file then don't write anything. */
1657 if ( gblErrorCount > 0 )
1660 /* Anlayze Machine will find the final action reference counts, among
1661 * other things. We will use these in reporting the usage
1662 * of fsm directives in action code. */
1665 /* Determine if we should use indicies. */
1669 ostream &JavaTabCodeGen::source_warning( const InputLoc &loc )
1671 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
1675 ostream &JavaTabCodeGen::source_error( const InputLoc &loc )
1678 assert( sourceFileName != 0 );
1679 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";