diff options
Diffstat (limited to 'libfsm/goto.cc')
-rw-r--r-- | libfsm/goto.cc | 978 |
1 files changed, 0 insertions, 978 deletions
diff --git a/libfsm/goto.cc b/libfsm/goto.cc deleted file mode 100644 index 610f44d1..00000000 --- a/libfsm/goto.cc +++ /dev/null @@ -1,978 +0,0 @@ -/* - * Copyright 2001-2018 Adrian Thurston <thurston@colm.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "ragel.h" -#include "goto.h" -#include "redfsm.h" -#include "bstmap.h" -#include "gendata.h" - -#include <sstream> - -using std::ostringstream; - -IpLabel *Goto::allocateLabels( IpLabel *labels, IpLabel::Type type, int n ) -{ - if ( labels == 0 ) { - labels = new IpLabel[n]; - for ( int id = 0; id < n; id++ ) { - labels[id].type = type; - labels[id].stid = id; - } - } - - return labels; -} - -void Goto::setTableState( TableArray::State state ) -{ - for ( ArrayVector::Iter i = arrayVector; i.lte(); i++ ) { - TableArray *tableArray = *i; - tableArray->setState( state ); - } -} - -/* Emit the goto to take for a given transition. */ -std::ostream &Goto::COND_GOTO( RedCondPair *cond ) -{ - out << "goto " << ctrLabel[cond->id].reference() << ";"; - return out; -} - -/* Emit the goto to take for a given transition. */ -std::ostream &Goto::TRANS_GOTO( RedTransAp *trans ) -{ - if ( trans->condSpace == 0 || trans->condSpace->condSet.length() == 0 ) { - /* Existing. */ - assert( trans->numConds() == 1 ); - RedCondPair *cond = trans->outCond( 0 ); - - /* Go to the transition which will go to the state. */ - out << "goto " << ctrLabel[cond->id].reference() << ";"; - } - else { - out << ck << " = 0;\n"; - for ( GenCondSet::Iter csi = trans->condSpace->condSet; csi.lte(); csi++ ) { - out << "if ( "; - CONDITION( out, *csi ); - Size condValOffset = (1 << csi.pos()); - out << " )\n" << ck << " += " << condValOffset << ";\n"; - } - CondKey lower = 0; - CondKey upper = trans->condFullSize() - 1; - COND_B_SEARCH( trans, lower, upper, 0, trans->numConds()-1 ); - - if ( trans->errCond() != 0 ) { - COND_GOTO( trans->errCond() ) << "\n"; - } - } - - return out; -} - -/* Write out the array of actions. */ -void Goto::taActions() -{ - actions.start(); - - actions.value( 0 ); - - for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { - /* Write out the length, which will never be the last character. */ - actions.value( act->key.length() ); - - for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) - actions.value( item->value->actionId ); - } - - actions.finish(); -} - -void Goto::GOTO_HEADER( RedStateAp *state ) -{ - /* Label the state. */ - out << "case " << state->id << ":\n"; -} - - -void Goto::SINGLE_SWITCH( RedStateAp *state ) -{ - /* Load up the singles. */ - int numSingles = state->outSingle.length(); - RedTransEl *data = state->outSingle.data; - - if ( numSingles == 1 ) { - /* If there is a single single key then write it out as an if. */ - out << "if ( " << GET_KEY() << " == " << - KEY(data[0].lowKey) << " ) {\n"; - - /* Virtual function for writing the target of the transition. */ - TRANS_GOTO(data[0].value) << "\n"; - out << "}\n"; - } - else if ( numSingles > 1 ) { - /* Write out single keys in a switch if there is more than one. */ - out << "switch( " << GET_KEY() << " ) {\n"; - - /* Write out the single indices. */ - for ( int j = 0; j < numSingles; j++ ) { - out << "case " << KEY(data[j].lowKey) << ": {\n"; - TRANS_GOTO(data[j].value) << "\n"; - out << "}\n"; - } - - /* Close off the transition switch. */ - out << "}\n"; - } -} - -void Goto::RANGE_B_SEARCH( RedStateAp *state, Key lower, Key upper, int low, int high ) -{ - /* Get the mid position, staying on the lower end of the range. */ - int mid = (low + high) >> 1; - RedTransEl *data = state->outRange.data; - - /* Determine if we need to look higher or lower. */ - bool anyLower = mid > low; - bool anyHigher = mid < high; - - /* Determine if the keys at mid are the limits of the alphabet. */ - bool limitLow = keyOps->eq( data[mid].lowKey, lower ); - bool limitHigh = keyOps->eq( data[mid].highKey, upper ); - - if ( anyLower && anyHigher ) { - /* Can go lower and higher than mid. */ - out << "if ( " << GET_KEY() << " < " << - KEY(data[mid].lowKey) << " ) {\n"; - RANGE_B_SEARCH( state, lower, keyOps->sub( data[mid].lowKey, 1 ), low, mid-1 ); - out << "} else if ( " << GET_KEY() << " > " << - KEY(data[mid].highKey) << " ) {\n"; - RANGE_B_SEARCH( state, keyOps->add( data[mid].highKey, 1 ), upper, mid+1, high ); - out << "} else {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else if ( anyLower && !anyHigher ) { - /* Can go lower than mid but not higher. */ - out << "if ( " << GET_KEY() << " < " << - KEY(data[mid].lowKey) << " ) {\n"; - RANGE_B_SEARCH( state, lower, keyOps->sub( data[mid].lowKey, 1 ), low, mid-1 ); - - /* if the higher is the highest in the alphabet then there is no - * sense testing it. */ - if ( limitHigh ) { - out << "} else {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else { - out << "} else if ( " << GET_KEY() << " <= " << - KEY(data[mid].highKey) << " ) {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - } - else if ( !anyLower && anyHigher ) { - /* Can go higher than mid but not lower. */ - out << "if ( " << GET_KEY() << " > " << - KEY(data[mid].highKey) << " ) {\n"; - RANGE_B_SEARCH( state, keyOps->add( data[mid].highKey, 1 ), upper, mid+1, high ); - - /* If the lower end is the lowest in the alphabet then there is no - * sense testing it. */ - if ( limitLow ) { - out << "} else {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else { - out << "} else if ( " << GET_KEY() << " >= " << - KEY(data[mid].lowKey) << " ) {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - } - else { - /* Cannot go higher or lower than mid. It's mid or bust. What - * tests to do depends on limits of alphabet. */ - if ( !limitLow && !limitHigh ) { - out << "if ( " << KEY(data[mid].lowKey) << " <= " << - GET_KEY() << " && " << GET_KEY() << " <= " << - KEY(data[mid].highKey) << " ) {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else if ( limitLow && !limitHigh ) { - out << "if ( " << GET_KEY() << " <= " << - KEY(data[mid].highKey) << " ) {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else if ( !limitLow && limitHigh ) { - out << "if ( " << KEY(data[mid].lowKey) << " <= " << - GET_KEY() << " ) {\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - else { - /* Both high and low are at the limit. No tests to do. */ - out << "{\n"; - TRANS_GOTO(data[mid].value) << "\n"; - out << "}\n"; - } - } -} - -/* Write out a key from the fsm code gen. Depends on wether or not the key is - * signed. */ -string Goto::CKEY( CondKey key ) -{ - ostringstream ret; - ret << key.getVal(); - return ret.str(); -} - -void Goto::COND_B_SEARCH( RedTransAp *trans, CondKey lower, - CondKey upper, int low, int high ) -{ - /* Get the mid position, staying on the lower end of the range. */ - int mid = (low + high) >> 1; -// RedCondEl *data = trans->outCond(0); - - /* Determine if we need to look higher or lower. */ - bool anyLower = mid > low; - bool anyHigher = mid < high; - - CondKey midKey = trans->outCondKey( mid ); - RedCondPair *midTrans = trans->outCond( mid ); - - /* Determine if the keys at mid are the limits of the alphabet. */ - bool limitLow = midKey == lower; - bool limitHigh = midKey == upper; - - if ( anyLower && anyHigher ) { - /* Can go lower and higher than mid. */ - out << "if ( " << ck << " < " << - CKEY(midKey) << " ) {\n"; - COND_B_SEARCH( trans, lower, midKey-1, low, mid-1 ); - out << "} else if ( " << ck << " > " << - CKEY(midKey) << " ) {\n"; - COND_B_SEARCH( trans, midKey+1, upper, mid+1, high ); - out << "} else {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else if ( anyLower && !anyHigher ) { - /* Can go lower than mid but not higher. */ - out << "if ( " << ck << " < " << - CKEY(midKey) << " ) {\n"; - COND_B_SEARCH( trans, lower, midKey-1, low, mid-1); - - /* if the higher is the highest in the alphabet then there is no - * sense testing it. */ - if ( limitHigh ) { - out << "} else {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else { - out << "} else if ( " << ck << " <= " << - CKEY(midKey) << " ) {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - } - else if ( !anyLower && anyHigher ) { - /* Can go higher than mid but not lower. */ - out << "if ( " << ck << " > " << - CKEY(midKey) << " ) {\n"; - COND_B_SEARCH( trans, midKey+1, upper, mid+1, high ); - - /* If the lower end is the lowest in the alphabet then there is no - * sense testing it. */ - if ( limitLow ) { - out << "} else {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else { - out << "} else if ( " << ck << " >= " << - CKEY(midKey) << " ) {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - } - else { - /* Cannot go higher or lower than mid. It's mid or bust. What - * tests to do depends on limits of alphabet. */ - if ( !limitLow && !limitHigh ) { - out << "if ( " << ck << " == " << - CKEY(midKey) << " ) {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else if ( limitLow && !limitHigh ) { - out << "if ( " << ck << " <= " << - CKEY(midKey) << " ) {\n"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else if ( !limitLow && limitHigh ) { - out << "if ( " << CKEY(midKey) << " <= " << ck << " )\n {"; - COND_GOTO(midTrans) << "\n"; - out << "}\n"; - } - else { - /* Both high and low are at the limit. No tests to do. */ - COND_GOTO(midTrans) << "\n"; - } - } -} - -void Goto::STATE_GOTO_ERROR() -{ - /* Bail out immediately. */ - out << " goto " << _again << ";\n"; -} - -void Goto::FROM_STATE_ACTION_EMIT( RedStateAp *state ) -{ - if ( state->fromStateAction != 0 ) { - /* Write every action in the list. */ - for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) { - ACTION( out, item->value, IlOpts( state->id, false, - state->fromStateAction->anyNextStmt() ) ); - out << "\n"; - } - } -} - -std::ostream &Goto::STATE_CASES() -{ - bool eof = redFsm->anyEofActivity() || redFsm->anyNfaStates(); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - /* Writing code above state gotos. */ - GOTO_HEADER( st ); - - FROM_STATE_ACTION_EMIT( st ); - - if ( !noEnd && eof ) { - out << - "if ( " << P() << " == " << vEOF() << " ) {\n"; - - if ( st->eofTrans != 0 ) - TRANS_GOTO( st->eofTrans ); - - out << - " goto " << _again << ";\n" - "}\n" - "else {\n"; - } - - if ( st == redFsm->errState ) - STATE_GOTO_ERROR(); - else { - /* Try singles. */ - if ( st->outSingle.length() > 0 ) - SINGLE_SWITCH( st ); - - /* Default case is to binary search for the ranges, if that fails then */ - if ( st->outRange.length() > 0 ) { - RANGE_B_SEARCH( st, keyOps->minKey, keyOps->maxKey, - 0, st->outRange.length() - 1 ); - } - - /* Write the default transition. */ - TRANS_GOTO( st->defTrans ) << "\n"; - } - - if ( !noEnd && eof ) { - out << - "}\n"; - } - } - return out; -} - -std::ostream &Goto::TRANSITION( RedCondPair *pair ) -{ - /* Write the label for the transition so it can be jumped to. */ - if ( ctrLabel[pair->id].isReferenced ) - out << "_ctr" << pair->id << ": "; - - /* Destination state. */ - if ( pair->action != 0 && pair->action->anyCurStateRef() ) - out << ps << " = " << vCS() << ";"; - out << vCS() << " = " << pair->targ->id << "; "; - - if ( pair->action != 0 ) { - /* Write out the transition func. */ - out << "goto f" << pair->action->actListId << ";\n"; - } - else { - /* No code to execute, just loop around. */ - out << "goto " << _again << ";\n"; - } - return out; -} - -std::ostream &Goto::TRANSITIONS() -{ - for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { - if ( trans->condSpace == 0 ) - TRANSITION( &trans->p ); - } - - for ( CondApSet::Iter cond = redFsm->condSet; cond.lte(); cond++ ) - TRANSITION( &cond->p ); - - return out; -} - -unsigned int Goto::TO_STATE_ACTION( RedStateAp *state ) -{ - int act = 0; - if ( state->toStateAction != 0 ) - act = state->toStateAction->location+1; - return act; -} - -unsigned int Goto::FROM_STATE_ACTION( RedStateAp *state ) -{ - int act = 0; - if ( state->fromStateAction != 0 ) - act = state->fromStateAction->location+1; - return act; -} - -unsigned int Goto::EOF_ACTION( RedStateAp *state ) -{ - int act = 0; - if ( state->eofAction != 0 ) - act = state->eofAction->location+1; - return act; -} - -void Goto::taToStateActions() -{ - toStateActions.start(); - - /* Take one off for the psuedo start state. */ - int numStates = redFsm->stateList.length(); - unsigned int *vals = new unsigned int[numStates]; - memset( vals, 0, sizeof(unsigned int)*numStates ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - vals[st->id] = TO_STATE_ACTION(st); - - for ( int st = 0; st < redFsm->nextStateId; st++ ) { - /* Write any eof action. */ - toStateActions.value( vals[st] ); - } - delete[] vals; - - toStateActions.finish(); -} - -void Goto::taFromStateActions() -{ - fromStateActions.start(); - - /* Take one off for the psuedo start state. */ - int numStates = redFsm->stateList.length(); - unsigned int *vals = new unsigned int[numStates]; - memset( vals, 0, sizeof(unsigned int)*numStates ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - vals[st->id] = FROM_STATE_ACTION(st); - - for ( int st = 0; st < redFsm->nextStateId; st++ ) { - /* Write any eof action. */ - fromStateActions.value( vals[st] ); - } - delete[] vals; - - fromStateActions.finish(); -} - -void Goto::taEofActions() -{ - eofActions.start(); - - /* Take one off for the psuedo start state. */ - int numStates = redFsm->stateList.length(); - unsigned int *vals = new unsigned int[numStates]; - memset( vals, 0, sizeof(unsigned int)*numStates ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - vals[st->id] = EOF_ACTION(st); - - for ( int st = 0; st < redFsm->nextStateId; st++ ) { - /* Write any eof action. */ - eofActions.value( vals[st] ); - } - delete[] vals; - - eofActions.finish(); -} - -void Goto::taNfaOffsets() -{ - nfaOffsets.start(); - - /* Offset of zero means no NFA targs, real targs start at 1. */ - long offset = 1; - - /* Take one off for the psuedo start state. */ - int numStates = redFsm->stateList.length(); - unsigned int *vals = new unsigned int[numStates]; - memset( vals, 0, sizeof(unsigned int)*numStates ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->nfaTargs == 0 ) { - vals[st->id] = 0; - //nfaOffsets.value( 0 ); - } - else { - vals[st->id] = offset; - //nfaOffsets.value( offset ); - offset += 1 + st->nfaTargs->length(); - } - } - - for ( int st = 0; st < redFsm->nextStateId; st++ ) - nfaOffsets.value( vals[st] ); - delete[] vals; - - nfaOffsets.finish(); -} - -void Goto::taNfaTargs() -{ - nfaTargs.start(); - - /* Offset of zero means no NFA targs, put a filler there. */ - nfaTargs.value( 0 ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->nfaTargs != 0 ) { - nfaTargs.value( st->nfaTargs->length() ); - for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ ) - nfaTargs.value( targ->state->id ); - } - } - - nfaTargs.finish(); -} - -/* These need to mirror nfa targs. */ -void Goto::taNfaPushActions() -{ - nfaPushActions.start(); - - nfaPushActions.value( 0 ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->nfaTargs != 0 ) { - nfaPushActions.value( 0 ); - for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ ) - NFA_PUSH_ACTION( targ ); - } - } - - nfaPushActions.finish(); -} - -void Goto::taNfaPopTrans() -{ - nfaPopTrans.start(); - - nfaPopTrans.value( 0 ); - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->nfaTargs != 0 ) { - nfaPopTrans.value( 0 ); - for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ ) - NFA_POP_TEST( targ ); - } - } - - nfaPopTrans.finish(); -} - -void Goto::EOF_CHECK( ostream &ret ) -{ - ret << - " if ( " << P() << " == " << PE() << " )\n" - " goto " << _test_eof << ";\n"; -} - -void Goto::GOTO( ostream &ret, int gotoDest, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK() << vCS() << " = " << gotoDest << "; "; - - if ( inFinish && !noEnd ) - EOF_CHECK( ret ); - - ret << "goto " << _again << ";"; - - ret << CLOSE_GEN_BLOCK(); -} - -void Goto::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK() << vCS() << " = " << OPEN_HOST_EXPR(); - INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << CLOSE_HOST_EXPR() << ";"; - - if ( inFinish && !noEnd ) - EOF_CHECK( ret ); - - ret << " goto " << _again << ";"; - - ret << CLOSE_GEN_BLOCK(); -} - -void Goto::CURS( ostream &ret, bool inFinish ) -{ - ret << "(" << ps << ")"; -} - -void Goto::TARGS( ostream &ret, bool inFinish, int targState ) -{ - ret << "(" << vCS() << ")"; -} - -void Goto::NEXT( ostream &ret, int nextDest, bool inFinish ) -{ - ret << vCS() << " = " << nextDest << ";"; -} - -void Goto::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) -{ - ret << vCS() << " = ("; - INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << ");"; -} - -void Goto::CALL( ostream &ret, int callDest, int targState, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK(); - - if ( red->prePushExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->prePushExpr ); - INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << - TOP() << " += 1;" << vCS() << " = " << - callDest << ";"; - - if ( inFinish && !noEnd ) - EOF_CHECK( ret ); - - ret << " goto " << _again << ";"; - - ret << CLOSE_GEN_BLOCK(); -} - -void Goto::NCALL( ostream &ret, int callDest, int targState, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK(); - - if ( red->prePushExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->prePushExpr ); - INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << - TOP() << " += 1;" << vCS() << " = " << - callDest << "; " << CLOSE_GEN_BLOCK(); -} - -void Goto::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK(); - - if ( red->prePushExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->prePushExpr ); - INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << TOP() << " += 1;" << - vCS() << " = " << OPEN_HOST_EXPR(); - INLINE_LIST( ret, ilItem->children, targState, inFinish, false ); - ret << CLOSE_HOST_EXPR() << ";"; - - if ( inFinish && !noEnd ) - EOF_CHECK( ret ); - - ret << " goto " << _again << ";"; - - ret << CLOSE_GEN_BLOCK(); -} - -void Goto::NCALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK(); - - if ( red->prePushExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->prePushExpr ); - INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << TOP() << " += 1;" << - vCS() << " = " << OPEN_HOST_EXPR(); - INLINE_LIST( ret, ilItem->children, targState, inFinish, false ); - ret << CLOSE_HOST_EXPR() << "; " << CLOSE_GEN_BLOCK(); -} - -void Goto::RET( ostream &ret, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK() << TOP() << "-= 1;" << vCS() << " = " << STACK() << "[" << TOP() << "];"; - - if ( red->postPopExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->postPopExpr ); - INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - if ( inFinish && !noEnd ) - EOF_CHECK( ret ); - - ret << "goto " << _again << ";" << CLOSE_GEN_BLOCK(); -} - -void Goto::NRET( ostream &ret, bool inFinish ) -{ - ret << OPEN_GEN_BLOCK() << TOP() << "-= 1;" << vCS() << " = " << STACK() << "[" << TOP() << "];"; - - if ( red->postPopExpr != 0 ) { - ret << OPEN_HOST_BLOCK( red->postPopExpr ); - INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ); - ret << CLOSE_HOST_BLOCK(); - } - - ret << CLOSE_GEN_BLOCK(); -} - -void Goto::BREAK( ostream &ret, int targState, bool csForced ) -{ - ret << OPEN_GEN_BLOCK() << P() << " += 1; " << "goto " << _out << "; " << CLOSE_GEN_BLOCK(); -} - -void Goto::NBREAK( ostream &ret, int targState, bool csForced ) -{ - ret << OPEN_GEN_BLOCK() << P() << " += 1; " << nbreak << " = 1; " << CLOSE_GEN_BLOCK(); -} - -void Goto::tableDataPass() -{ - if ( type == Loop ) - taActions(); - - taToStateActions(); - taFromStateActions(); - taEofActions(); - - taNfaTargs(); - taNfaOffsets(); - taNfaPushActions(); - taNfaPopTrans(); -} - -void Goto::genAnalysis() -{ - /* For directly executable machines there is no required state - * ordering. Choose a depth-first ordering to increase the - * potential for fall-throughs. */ - redFsm->depthFirstOrdering(); - - /* Choose default transitions and the single transition. */ - redFsm->chooseDefaultSpan(); - - /* Choose single. */ - redFsm->moveSelectTransToSingle(); - - /* If any errors have occured in the input file then don't write anything. */ - if ( red->id->errorCount > 0 ) - return; - - /* Anlayze Machine will find the final action reference counts, among other - * things. We will use these in reporting the usage of fsm directives in - * action code. */ - red->analyzeMachine(); - - /* Run the analysis pass over the table data. */ - setTableState( TableArray::AnalyzePass ); - tableDataPass(); - - /* Switch the tables over to the code gen mode. */ - setTableState( TableArray::GeneratePass ); -} - -void Goto::writeData() -{ - if ( type == Loop ) { - if ( redFsm->anyActions() ) - taActions(); - } - - if ( redFsm->anyToStateActions() ) - taToStateActions(); - - if ( redFsm->anyFromStateActions() ) - taFromStateActions(); - - if ( redFsm->anyEofActions() ) - taEofActions(); - - taNfaTargs(); - taNfaOffsets(); - taNfaPushActions(); - taNfaPopTrans(); - - STATE_IDS(); -} - -void Goto::writeExec() -{ - int maxCtrId = redFsm->nextCondId > redFsm->nextTransId ? redFsm->nextCondId : redFsm->nextTransId; - ctrLabel = allocateLabels( ctrLabel, IpLabel::Ctr, maxCtrId ); - - out << "{\n"; - - DECLARE( INT(), cpc ); - DECLARE( INT(), ck ); - DECLARE( INT(), pop_test ); - DECLARE( INT(), nbreak ); - DECLARE( INT(), ps, " = 0" ); - DECLARE( INT(), new_recs ); - DECLARE( INT(), alt ); - DECLARE( INDEX( ARR_TYPE( actions ) ), acts ); - DECLARE( UINT(), nacts ); - - out << "\n"; - - out << EMIT_LABEL( _resume ); - - /* Do we break out on no more input. */ - bool eof = redFsm->anyEofActivity() || redFsm->anyNfaStates(); - if ( !noEnd ) { - if ( eof ) { - out << - " if ( " << P() << " == " << PE() << " && " << P() << " != " << vEOF() << " )\n" - " goto " << _out << ";\n"; - } - else { - out << - " if ( " << P() << " == " << PE() << " )\n" - " goto " << _out << ";\n"; - } - } - - NFA_PUSH( vCS() ); - - out << - " switch ( " << vCS() << " ) {\n"; - STATE_CASES() << - " }\n" - "\n"; - TRANSITIONS() << - "\n"; - - if ( redFsm->anyRegActions() ) - EXEC_FUNCS() << "\n"; - - out << EMIT_LABEL( _again ); - - if ( !noEnd && eof ) { - out << - " if ( " << P() << " == " << vEOF() << " ) {\n" - " if ( " << vCS() << " >= " << FIRST_FINAL_STATE() << " )\n" - " goto " << _out << ";\n" - " }\n" - " else {\n"; - } - - TO_STATE_ACTIONS(); - - if ( redFsm->errState != 0 ) { - out << - " if ( " << vCS() << " != " << redFsm->errState->id << " ) {\n"; - } - - out << - " " << P() << " += 1;\n" - " goto " << _resume << ";\n"; - - if ( redFsm->errState != 0 ) { - out << - " }\n"; - } - - if ( !noEnd && eof ) { - out << - " }\n"; - } - - if ( redFsm->anyNfaStates() ) { - out << - " if ( nfa_len == 0 )\n" - " goto " << _out << ";\n" - "\n" - " nfa_count += 1;\n" - " nfa_len -= 1;\n" - " " << P() << " = nfa_bp[nfa_len].p;\n" - ; - - if ( redFsm->bAnyNfaPops ) { - NFA_FROM_STATE_ACTION_EXEC(); - - NFA_POP_TEST_EXEC(); - - out << - " if ( " << pop_test << " )\n" - " " << vCS() << " = nfa_bp[nfa_len].state;\n" - " else\n" - " " << vCS() << " = " << ERROR_STATE() << ";\n"; - } - else { - out << - " " << vCS() << " = nfa_bp[nfa_len].state;\n"; - - } - - NFA_POST_POP(); - - out << "goto " << _resume << ";\n"; - } - - out << EMIT_LABEL( _out ); - - out << "}\n"; -} |