ipgoto.cc (ragel-7.0.0.11) | : | ipgoto.cc (ragel-7.0.0.12) | ||
---|---|---|---|---|
skipping to change at line 86 | skipping to change at line 86 | |||
{ | { | |||
return redFsm->anyActionRets() || | return redFsm->anyActionRets() || | |||
redFsm->anyActionByValControl() || | redFsm->anyActionByValControl() || | |||
redFsm->anyRegNextStmt(); | redFsm->anyRegNextStmt(); | |||
} | } | |||
void IpGoto::EOF_CHECK( ostream &ret, int gotoDest ) | void IpGoto::EOF_CHECK( ostream &ret, int gotoDest ) | |||
{ | { | |||
ret << | ret << | |||
" if ( " << P() << " == " << PE() << " )\n" | " if ( " << P() << " == " << PE() << " )\n" | |||
" goto _test_eof" << gotoDest << ";\n"; | " goto " << eofLabel[gotoDest].reference() << ";\n" | |||
; | ||||
testEofUsed = true; | ||||
} | } | |||
void IpGoto::GOTO( ostream &ret, int gotoDest, bool inFinish ) | void IpGoto::GOTO( ostream &ret, int gotoDest, bool inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK(); | ret << OPEN_GEN_BLOCK(); | |||
if ( inFinish && !noEnd ) | if ( inFinish && !noEnd ) | |||
EOF_CHECK( ret, gotoDest ); | EOF_CHECK( ret, gotoDest ); | |||
ret << "goto st" << gotoDest << ";"; | ret << "goto " << stLabel[gotoDest].reference() << ";"; | |||
ret << CLOSE_GEN_BLOCK(); | ret << CLOSE_GEN_BLOCK(); | |||
} | } | |||
void IpGoto::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) | void IpGoto::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK() << vCS() << " = " << OPEN_HOST_EXPR(); | ret << OPEN_GEN_BLOCK() << vCS() << " = " << OPEN_HOST_EXPR(); | |||
INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | |||
ret << CLOSE_HOST_EXPR() << ";"; | ret << CLOSE_HOST_EXPR() << ";"; | |||
/* Since we are setting CS above and can select on it, call the all-state | /* Since we are setting CS above and can select on it, call the all-state | |||
* test_eof. */ | * test_eof. */ | |||
if ( inFinish && !noEnd ) | if ( inFinish && !noEnd ) | |||
CodeGen::EOF_CHECK( ret ); | Goto::EOF_CHECK( ret ); | |||
ret << " goto _again;"; | ret << " goto " << _again << ";"; | |||
ret << CLOSE_GEN_BLOCK(); | ret << CLOSE_GEN_BLOCK(); | |||
} | } | |||
void IpGoto::CALL( ostream &ret, int callDest, int targState, bool inFinish ) | void IpGoto::CALL( ostream &ret, int callDest, int targState, bool inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK(); | ret << OPEN_GEN_BLOCK(); | |||
if ( red->prePushExpr != 0 ) { | if ( red->prePushExpr != 0 ) { | |||
ret << OPEN_HOST_BLOCK( red->prePushExpr ); | ret << OPEN_HOST_BLOCK( red->prePushExpr ); | |||
INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ) ; | INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false ) ; | |||
ret << CLOSE_HOST_BLOCK(); | ret << CLOSE_HOST_BLOCK(); | |||
} | } | |||
ret << STACK() << "[" << TOP() << "] = " << targState << | ret << STACK() << "[" << TOP() << "] = " << targState << | |||
"; " << TOP() << "+= 1; "; | "; " << TOP() << "+= 1; "; | |||
if ( inFinish && !noEnd ) | if ( inFinish && !noEnd ) | |||
EOF_CHECK( ret, callDest ); | EOF_CHECK( ret, callDest ); | |||
ret << "goto st" << callDest << ";"; | ret << "goto " << stLabel[callDest].reference() << ";"; | |||
ret << CLOSE_GEN_BLOCK(); | ret << CLOSE_GEN_BLOCK(); | |||
} | } | |||
void IpGoto::NCALL( ostream &ret, int callDest, int targState, bool inFinish ) | void IpGoto::NCALL( ostream &ret, int callDest, int targState, bool inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK(); | ret << OPEN_GEN_BLOCK(); | |||
if ( red->prePushExpr != 0 ) { | if ( red->prePushExpr != 0 ) { | |||
ret << OPEN_HOST_BLOCK( red->prePushExpr ); | ret << OPEN_HOST_BLOCK( red->prePushExpr ); | |||
skipping to change at line 173 | skipping to change at line 171 | |||
} | } | |||
ret << STACK() << "[" << TOP() << "] = " << targState << "; " << TOP() << "+= 1;" << | ret << STACK() << "[" << TOP() << "] = " << targState << "; " << TOP() << "+= 1;" << | |||
vCS() << " = " << OPEN_HOST_EXPR(); | vCS() << " = " << OPEN_HOST_EXPR(); | |||
INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | |||
ret << CLOSE_HOST_EXPR() << ";"; | ret << CLOSE_HOST_EXPR() << ";"; | |||
/* Since we are setting CS above and can select on it, call the all-state | /* Since we are setting CS above and can select on it, call the all-state | |||
* test_eof. */ | * test_eof. */ | |||
if ( inFinish && !noEnd ) | if ( inFinish && !noEnd ) | |||
CodeGen::EOF_CHECK( ret ); | Goto::EOF_CHECK( ret ); | |||
ret << " goto _again;"; | ret << " goto " << _again << ";"; | |||
ret << CLOSE_GEN_BLOCK(); | ret << CLOSE_GEN_BLOCK(); | |||
} | } | |||
void IpGoto::NCALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, boo l inFinish ) | void IpGoto::NCALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, boo l inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK(); | ret << OPEN_GEN_BLOCK(); | |||
if ( red->prePushExpr != 0 ) { | if ( red->prePushExpr != 0 ) { | |||
ret << OPEN_HOST_BLOCK( red->prePushExpr ); | ret << OPEN_HOST_BLOCK( red->prePushExpr ); | |||
skipping to change at line 208 | skipping to change at line 206 | |||
ret << OPEN_GEN_BLOCK() << TOP() << " -= 1;" << vCS() << " = " | ret << OPEN_GEN_BLOCK() << TOP() << " -= 1;" << vCS() << " = " | |||
<< STACK() << "[" << TOP() << "];"; | << STACK() << "[" << TOP() << "];"; | |||
if ( red->postPopExpr != 0 ) { | if ( red->postPopExpr != 0 ) { | |||
ret << OPEN_HOST_BLOCK( red->postPopExpr ); | ret << OPEN_HOST_BLOCK( red->postPopExpr ); | |||
INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ) ; | INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ) ; | |||
ret << CLOSE_HOST_BLOCK(); | ret << CLOSE_HOST_BLOCK(); | |||
} | } | |||
if ( inFinish && !noEnd ) | if ( inFinish && !noEnd ) | |||
CodeGen::EOF_CHECK( ret ); | Goto::EOF_CHECK( ret ); | |||
ret << "goto _again;" << CLOSE_GEN_BLOCK(); | ret << "goto " << _again << ";" << CLOSE_GEN_BLOCK(); | |||
} | } | |||
void IpGoto::NRET( ostream &ret, bool inFinish ) | void IpGoto::NRET( ostream &ret, bool inFinish ) | |||
{ | { | |||
ret << OPEN_GEN_BLOCK() << TOP() << " -= 1;" << vCS() << " = " | ret << OPEN_GEN_BLOCK() << TOP() << " -= 1;" << vCS() << " = " | |||
<< STACK() << "[" << TOP() << "];"; | << STACK() << "[" << TOP() << "];"; | |||
if ( red->postPopExpr != 0 ) { | if ( red->postPopExpr != 0 ) { | |||
ret << OPEN_HOST_BLOCK( red->postPopExpr ); | ret << OPEN_HOST_BLOCK( red->postPopExpr ); | |||
INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ) ; | INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false ) ; | |||
skipping to change at line 241 | skipping to change at line 239 | |||
void IpGoto::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) | void IpGoto::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) | |||
{ | { | |||
ret << vCS() << " = ("; | ret << vCS() << " = ("; | |||
INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); | |||
ret << ");"; | ret << ");"; | |||
} | } | |||
void IpGoto::CURS( ostream &ret, bool inFinish ) | void IpGoto::CURS( ostream &ret, bool inFinish ) | |||
{ | { | |||
ret << "(_ps)"; | ret << "(" << ps << ")"; | |||
} | } | |||
void IpGoto::TARGS( ostream &ret, bool inFinish, int targState ) | void IpGoto::TARGS( ostream &ret, bool inFinish, int targState ) | |||
{ | { | |||
ret << targState; | ret << targState; | |||
} | } | |||
void IpGoto::BREAK( ostream &ret, int targState, bool csForced ) | void IpGoto::BREAK( ostream &ret, int targState, bool csForced ) | |||
{ | { | |||
outLabelUsed = true; | ||||
ret << "{" << P() << "+= 1; "; | ret << "{" << P() << "+= 1; "; | |||
if ( !csForced ) | if ( !csForced ) | |||
ret << vCS() << " = " << targState << "; "; | ret << vCS() << " = " << targState << "; "; | |||
ret << "goto _out;}"; | ret << "goto " << _out << ";}"; | |||
} | } | |||
void IpGoto::NBREAK( ostream &ret, int targState, bool csForced ) | void IpGoto::NBREAK( ostream &ret, int targState, bool csForced ) | |||
{ | { | |||
outLabelUsed = true; | ||||
ret << "{" << P() << "+= 1; "; | ret << "{" << P() << "+= 1; "; | |||
if ( !csForced ) | if ( !csForced ) | |||
ret << vCS() << " = " << targState << "; "; | ret << vCS() << " = " << targState << "; "; | |||
ret << "_nbreak = 1;}"; | ret << nbreak << " = 1;}"; | |||
} | } | |||
void IpGoto::NFA_PUSH_ACTION( RedNfaTarg *targ ) | void IpGoto::NFA_PUSH_ACTION( RedNfaTarg *targ ) | |||
{ | { | |||
int act = 0; | int act = 0; | |||
if ( targ->push != 0 ) | if ( targ->push != 0 ) | |||
act = targ->push->actListId+1; | act = targ->push->actListId+1; | |||
nfaPushActions.value( act ); | nfaPushActions.value( act ); | |||
} | } | |||
skipping to change at line 296 | skipping to change at line 292 | |||
/* Emit any transitions that have actions and that go to this state. */ | /* Emit any transitions that have actions and that go to this state. */ | |||
for ( int it = 0; it < state->numInConds; it++ ) { | for ( int it = 0; it < state->numInConds; it++ ) { | |||
RedCondPair *trans = state->inConds[it]; | RedCondPair *trans = state->inConds[it]; | |||
if ( trans->action != 0 ) { | if ( trans->action != 0 ) { | |||
/* Remember that we wrote an action so we know to write t he | /* Remember that we wrote an action so we know to write t he | |||
* line directive for going back to the output. */ | * line directive for going back to the output. */ | |||
anyWritten = true; | anyWritten = true; | |||
/* Write the label for the transition so it can be jumped to. */ | /* Write the label for the transition so it can be jumped to. */ | |||
out << "ctr" << trans->id << ":\n"; | if ( ctrLabel[trans->id].isReferenced ) | |||
out << "_ctr" << trans->id << ":\n"; | ||||
/* If the action contains a next, then we must preload th e current | /* If the action contains a next, then we must preload th e current | |||
* state since the action may or may not set it. */ | * state since the action may or may not set it. */ | |||
if ( trans->action->anyNextStmt() ) | if ( trans->action->anyNextStmt() ) | |||
out << " " << vCS() << " = " << trans->tar g->id << ";\n"; | out << " " << vCS() << " = " << trans->tar g->id << ";\n"; | |||
if ( redFsm->anyRegNbreak() ) | if ( redFsm->anyRegNbreak() ) | |||
out << "_nbreak = 0;\n"; | out << nbreak << " = 0;\n"; | |||
/* Write each action in the list. */ | /* Write each action in the list. */ | |||
for ( GenActionTable::Iter item = trans->action->key; ite m.lte(); item++ ) { | for ( GenActionTable::Iter item = trans->action->key; ite m.lte(); item++ ) { | |||
ACTION( out, item->value, IlOpts( trans->targ->id , false, | ACTION( out, item->value, IlOpts( trans->targ->id , false, | |||
trans->action->anyNextStmt() ) ); | trans->action->anyNextStmt() ) ); | |||
out << "\n"; | out << "\n"; | |||
} | } | |||
if ( redFsm->anyRegNbreak() ) { | if ( redFsm->anyRegNbreak() ) { | |||
out << | out << | |||
"if ( _nbreak == 1 )\n" | "if ( " << nbreak << " == 1 )\n" | |||
" goto _out;\n"; | " goto " << _out << ";\n"; | |||
outLabelUsed = true; | ||||
} | } | |||
/* If the action contains a next then we need to reload, otherwise | /* If the action contains a next then we need to reload, otherwise | |||
* jump directly to the target state. */ | * jump directly to the target state. */ | |||
if ( trans->action->anyNextStmt() ) | if ( trans->action->anyNextStmt() ) | |||
out << "\n\tgoto _again;\n"; | out << "goto " << _again << ";\n"; | |||
else | else | |||
out << "\n\tgoto st" << trans->targ->id << ";\n"; | out << "goto " << stLabel[trans->targ->id].refere nce() << ";\n"; | |||
} | } | |||
} | } | |||
return anyWritten; | return anyWritten; | |||
} | } | |||
/* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for each | /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for each | |||
* state. */ | * state. */ | |||
void IpGoto::GOTO_HEADER( RedStateAp *state ) | void IpGoto::GOTO_HEADER( RedStateAp *state ) | |||
{ | { | |||
IN_TRANS_ACTIONS( state ); | IN_TRANS_ACTIONS( state ); | |||
if ( state->labelNeeded ) | if ( stLabel[state->id].isReferenced ) | |||
out << "st" << state->id << ":\n"; | out << "_st" << state->id << ":\n"; | |||
/* need to do this if the transition is an eof transition, or if the acti | ||||
on | ||||
* contains fexec. Otherwise, no need. */ | ||||
if ( redFsm->anyEofActivity() ) { | ||||
out << | ||||
"if ( " << P() << " == " << vEOF() << " ) {\n" | ||||
" if ( " << vCS() << " >= " << FIRST_FINAL_STATE() | ||||
<< " )\n" | ||||
" goto " << _out << ";\n" | ||||
" else\n" | ||||
" goto " << _pop << ";\n" | ||||
"}\n"; | ||||
} | ||||
if ( state->toStateAction != 0 ) { | if ( state->toStateAction != 0 ) { | |||
/* Write every action in the list. */ | /* Write every action in the list. */ | |||
for ( GenActionTable::Iter item = state->toStateAction->key; item .lte(); item++ ) { | for ( GenActionTable::Iter item = state->toStateAction->key; item .lte(); item++ ) { | |||
ACTION( out, item->value, IlOpts( state->id, false, | ACTION( out, item->value, IlOpts( state->id, false, | |||
state->toStateAction->anyNextStmt() ) ); | state->toStateAction->anyNextStmt() ) ); | |||
out << "\n"; | out << "\n"; | |||
} | } | |||
} | } | |||
/* Advance and test buffer pos. */ | /* Advance and test buffer pos. */ | |||
if ( state->labelNeeded ) { | if ( state->labelNeeded ) { | |||
if ( !noEnd ) { | if ( !noEnd ) { | |||
out << | out << | |||
" " << P() << "+= 1;\n" | P() << "+= 1;\n" | |||
" if ( " << P() << " == " << PE() << " )\n" | "if ( " << P() << " == " << PE() << " )\n" | |||
" goto _test_eof" << state->id << " | " goto " << eofLabel[state->id].reference() | |||
;\n"; | << ";\n"; | |||
} | } | |||
else { | else { | |||
out << | out << | |||
" " << P() << " += 1;\n"; | P() << " += 1;\n"; | |||
} | } | |||
} | } | |||
/* Give the state a switch case. */ | /* Give the state a switch case. */ | |||
out << "st_case_" << state->id << ":\n"; | out << "st_case_" << state->id << ":\n"; | |||
if ( state->fromStateAction != 0 ) { | if ( state->fromStateAction != 0 ) { | |||
/* Write every action in the list. */ | /* Write every action in the list. */ | |||
for ( GenActionTable::Iter item = state->fromStateAction->key; it em.lte(); item++ ) { | for ( GenActionTable::Iter item = state->fromStateAction->key; it em.lte(); item++ ) { | |||
ACTION( out, item->value, IlOpts( state->id, false, | ACTION( out, item->value, IlOpts( state->id, false, | |||
state->fromStateAction->anyNextStmt() ) ) ; | state->fromStateAction->anyNextStmt() ) ) ; | |||
out << "\n"; | out << "\n"; | |||
} | } | |||
} | } | |||
/* Record the prev state if necessary. */ | /* Record the prev state if necessary. */ | |||
if ( state->anyRegCurStateRef() ) | if ( state->anyRegCurStateRef() ) | |||
out << " _ps = " << state->id << ";\n"; | out << ps << " = " << state->id << ";\n"; | |||
} | } | |||
void IpGoto::STATE_GOTO_ERROR() | void IpGoto::STATE_GOTO_ERROR() | |||
{ | { | |||
/* In the error state we need to emit some stuff that usually goes into | /* In the error state we need to emit some stuff that usually goes into | |||
* the header. */ | * the header. */ | |||
RedStateAp *state = redFsm->errState; | RedStateAp *state = redFsm->errState; | |||
IN_TRANS_ACTIONS( state ); | IN_TRANS_ACTIONS( state ); | |||
out << "st_case_" << state->id << ":\n"; | out << "st_case_" << state->id << ":\n"; | |||
if ( state->labelNeeded ) | if ( stLabel[state->id].isReferenced ) | |||
out << "st" << state->id << ":\n"; | out << "_st" << state->id << ":\n"; | |||
/* Break out here. */ | /* Break out here. */ | |||
outLabelUsed = true; | ||||
out << vCS() << " = " << state->id << ";\n"; | out << vCS() << " = " << state->id << ";\n"; | |||
out << " goto _out;\n"; | out << "goto " << _pop << ";\n"; | |||
} | } | |||
/* Emit the goto to take for a given transition. */ | /* Emit the goto to take for a given transition. */ | |||
std::ostream &IpGoto::TRANS_GOTO( RedTransAp *trans, int level ) | std::ostream &IpGoto::TRANS_GOTO( RedTransAp *trans ) | |||
{ | { | |||
if ( trans->condSpace == 0 || trans->condSpace->condSet.length() == 0 ) { | if ( trans->condSpace == 0 || trans->condSpace->condSet.length() == 0 ) { | |||
/* Existing. */ | /* Existing. */ | |||
assert( trans->numConds() == 1 ); | assert( trans->numConds() == 1 ); | |||
RedCondPair *cond = trans->outCond( 0 ); | RedCondPair *cond = trans->outCond( 0 ); | |||
if ( cond->action != 0 ) { | if ( cond->action != 0 ) { | |||
/* Go to the transition which will go to the state. */ | /* Go to the transition which will go to the state. */ | |||
out << TABS(level) << "goto ctr" << cond->id << ";"; | out << "goto " << ctrLabel[trans->p.id].reference() << "; "; | |||
} | } | |||
else { | else { | |||
/* Go directly to the target state. */ | /* Go directly to the target state. */ | |||
out << TABS(level) << "goto st" << cond->targ->id << ";"; | out << "goto " << stLabel[cond->targ->id].reference() << ";"; | |||
} | } | |||
} | } | |||
else { | else { | |||
out << TABS(level) << "int ck = 0;\n"; | out << ck << " = 0;\n"; | |||
for ( GenCondSet::Iter csi = trans->condSpace->condSet; csi.lte() ; csi++ ) { | for ( GenCondSet::Iter csi = trans->condSpace->condSet; csi.lte() ; csi++ ) { | |||
out << TABS(level) << "if ( "; | out << "if ( "; | |||
CONDITION( out, *csi ); | CONDITION( out, *csi ); | |||
Size condValOffset = (1 << csi.pos()); | Size condValOffset = (1 << csi.pos()); | |||
out << " ) ck += " << condValOffset << ";\n"; | out << " )\n" << ck << " += " << condValOffset << ";\n"; | |||
} | } | |||
CondKey lower = 0; | CondKey lower = 0; | |||
CondKey upper = trans->condFullSize() - 1; | CondKey upper = trans->condFullSize() - 1; | |||
COND_B_SEARCH( trans, 1, lower, upper, 0, trans->numConds() - 1 ) ; | COND_B_SEARCH( trans, lower, upper, 0, trans->numConds() - 1 ); | |||
if ( trans->errCond() != 0 ) { | if ( trans->errCond() != 0 ) { | |||
COND_GOTO( trans->errCond(), level+1 ) << "\n"; | COND_GOTO( trans->errCond() ) << "\n"; | |||
} | } | |||
} | } | |||
return out; | return out; | |||
} | } | |||
/* Emit the goto to take for a given transition. */ | /* Emit the goto to take for a given transition. */ | |||
std::ostream &IpGoto::COND_GOTO( RedCondPair *cond, int level ) | std::ostream &IpGoto::COND_GOTO( RedCondPair *cond ) | |||
{ | { | |||
/* Existing. */ | /* Existing. */ | |||
if ( cond->action != 0 ) { | if ( cond->action != 0 ) { | |||
/* Go to the transition which will go to the state. */ | /* Go to the transition which will go to the state. */ | |||
out << TABS(level) << "goto ctr" << cond->id << ";"; | out << "goto " << ctrLabel[cond->id].reference() << ";"; | |||
} | } | |||
else { | else { | |||
/* Go directly to the target state. */ | /* Go directly to the target state. */ | |||
out << TABS(level) << "goto st" << cond->targ->id << ";"; | out << "goto " << stLabel[cond->targ->id].reference() << ";"; | |||
} | } | |||
return out; | return out; | |||
} | } | |||
std::ostream &IpGoto::EXIT_STATES() | std::ostream &IpGoto::EXIT_STATES() | |||
{ | { | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
if ( st->outNeeded ) { | if ( eofLabel[st->id].isReferenced ) { | |||
testEofUsed = true; | out << eofLabel[st->id].define() << ": " << vCS() << " = | |||
out << " _test_eof" << st->id << ": " << vCS() << | " << | |||
" = " << | st->id << "; goto " << _test_eof << "; \n | |||
st->id << "; goto _test_eof; \n"; | "; | |||
} | } | |||
} | } | |||
return out; | return out; | |||
} | } | |||
std::ostream &IpGoto::AGAIN_CASES() | std::ostream &IpGoto::AGAIN_CASES() | |||
{ | { | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
out << | out << | |||
" case " << st->id << ": goto st" << st->id << ";\n"; | "case " << st->id << ": goto " << stLabel[st->id].referen ce() << ";\n"; | |||
} | } | |||
return out; | return out; | |||
} | } | |||
std::ostream &IpGoto::STATE_GOTO_CASES() | std::ostream &IpGoto::STATE_GOTO_CASES() | |||
{ | { | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
out << TABS(1) << "case " << st->id << ":\n"; | out << "case " << st->id << ":\n"; | |||
out << TABS(2) << "goto st_case_" << st->id << ";\n"; | out << "goto st_case_" << st->id << ";\n"; | |||
} | } | |||
return out; | return out; | |||
} | } | |||
void IpGoto::NFA_PUSH( RedStateAp *state ) | void IpGoto::NFA_PUSH( RedStateAp *state ) | |||
{ | { | |||
std::stringstream ss; | std::stringstream ss; | |||
ss << state->id; | ss << state->id; | |||
CodeGen::NFA_PUSH( ss.str() ); | std::string _state = ss.str(); | |||
if ( redFsm->anyNfaStates() ) { | ||||
if ( state->nfaTargs != 0 ) { | ||||
out << | ||||
"if ( " << ARR_REF( nfaOffsets ) << "[" << _state | ||||
<< "] ) {\n" | ||||
" " << new_recs << " = " << state->nfaTargs | ||||
->length() << ";\n"; | ||||
if ( red->nfaPrePushExpr != 0 ) { | ||||
out << OPEN_HOST_BLOCK( red->nfaPrePushExpr ); | ||||
INLINE_LIST( out, red->nfaPrePushExpr->inlineList | ||||
, 0, false, false ); | ||||
out << CLOSE_HOST_BLOCK(); | ||||
} | ||||
int alt = 0; | ||||
for ( RedNfaTargs::Iter nt = *state->nfaTargs; nt.lte(); | ||||
nt++ ) { | ||||
out << | ||||
" nfa_bp[nfa_len].state = " << nt-> | ||||
state->id << ";\n" | ||||
" nfa_bp[nfa_len].p = " << P() << " | ||||
;\n"; | ||||
if ( nt->popTest != 0 ) { | ||||
out << | ||||
" nfa_bp[nfa_len].popTrans | ||||
= " << (nt->popTest->actListId+1) << ";\n"; | ||||
} | ||||
else if ( redFsm->bAnyNfaPops ) { | ||||
out << | ||||
" nfa_bp[nfa_len].popTrans | ||||
= 0;\n"; | ||||
} | ||||
if ( nt->push != 0 ) { | ||||
for ( GenActionTable::Iter item = nt->pus | ||||
h->key; item.lte(); item++ ) | ||||
ACTION( out, item->value, IlOpts( | ||||
0, false, false ) ); | ||||
} | ||||
out << | ||||
" nfa_len += 1;\n"; | ||||
alt += 1; | ||||
} | ||||
out << | ||||
"}\n"; | ||||
} | ||||
} | ||||
} | } | |||
std::ostream &IpGoto::STATE_GOTOS() | std::ostream &IpGoto::STATE_GOTOS() | |||
{ | { | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
if ( st == redFsm->errState ) | if ( st == redFsm->errState ) | |||
STATE_GOTO_ERROR(); | STATE_GOTO_ERROR(); | |||
else { | else { | |||
/* Writing code above state gotos. */ | /* Writing code above state gotos. */ | |||
GOTO_HEADER( st ); | GOTO_HEADER( st ); | |||
NFA_PUSH( st ); | NFA_PUSH( st ); | |||
/* Try singles. */ | /* Try singles. */ | |||
if ( st->outSingle.length() > 0 ) | if ( st->outSingle.length() > 0 ) | |||
SINGLE_SWITCH( st ); | SINGLE_SWITCH( st ); | |||
/* Default case is to binary search for the ranges, if th at fails then */ | /* Default case is to binary search for the ranges, if th at fails then */ | |||
if ( st->outRange.length() > 0 ) { | if ( st->outRange.length() > 0 ) { | |||
RANGE_B_SEARCH( st, 1, keyOps->minKey, keyOps->ma xKey, | RANGE_B_SEARCH( st, keyOps->minKey, keyOps->maxKe y, | |||
0, st->outRange.length() - 1 ); | 0, st->outRange.length() - 1 ); | |||
} | } | |||
/* Write the default transition. */ | /* Write the default transition. */ | |||
out << "{\n"; | out << "{\n"; | |||
TRANS_GOTO( st->defTrans, 1 ) << "\n"; | TRANS_GOTO( st->defTrans ) << "\n"; | |||
out << "}\n"; | out << "}\n"; | |||
} | } | |||
} | } | |||
return out; | return out; | |||
} | } | |||
std::ostream &IpGoto::FINISH_CASES() | std::ostream &IpGoto::FINISH_CASES() | |||
{ | { | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
if ( st->eofAction != 0 ) { | ||||
if ( st->eofAction->eofRefs == 0 ) | ||||
st->eofAction->eofRefs = new IntSet; | ||||
st->eofAction->eofRefs->insert( st->id ); | ||||
} | ||||
} | ||||
for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) | ||||
{ | ||||
if ( act->eofRefs != 0 ) { | ||||
for ( IntSet::Iter pst = *act->eofRefs; pst.lte(); pst++ | ||||
) { | ||||
out << " case " << *pst << ": \n"; | ||||
if ( ! pst.last() ) | ||||
out << " " << FALLTHROUGH( | ||||
) << "\n"; | ||||
} | ||||
/* Write each action in the eof action list. */ | ||||
for ( GenActionTable::Iter item = act->key; item.lte(); i | ||||
tem++ ) | ||||
ACTION( out, item->value, IlOpts( STATE_ERR_STATE | ||||
, true, false ) ); | ||||
out << "\n\tbreak;\n"; | ||||
} | ||||
} | ||||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | ||||
if ( st->eofTrans != 0 ) { | if ( st->eofTrans != 0 ) { | |||
RedCondPair *cond = st->eofTrans->outCond( 0 ); | out << | |||
out << " case " << st->id << ": goto ctr" << cond- | "case " << st->id << ":\n"; | |||
>id << ";\n"; | ||||
TRANS_GOTO( st->eofTrans ); | ||||
} | } | |||
} | } | |||
return out; | return out; | |||
} | } | |||
void IpGoto::setLabelsNeeded( GenInlineList *inlineList ) | void IpGoto::setLabelsNeeded( GenInlineList *inlineList ) | |||
{ | { | |||
for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { | for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { | |||
switch ( item->type ) { | switch ( item->type ) { | |||
case GenInlineItem::Goto: case GenInlineItem::Call: | case GenInlineItem::Goto: | |||
case GenInlineItem::Ncall: { | case GenInlineItem::Call: | |||
/* Mark the target as needing a label. */ | case GenInlineItem::Ncall: { | |||
item->targState->labelNeeded = true; | /* Mark the target as needing a label. */ | |||
break; | item->targState->labelNeeded = true; | |||
} | break; | |||
default: break; | } | |||
default: break; | ||||
} | } | |||
if ( item->children != 0 ) | if ( item->children != 0 ) | |||
setLabelsNeeded( item->children ); | setLabelsNeeded( item->children ); | |||
} | } | |||
} | } | |||
void IpGoto::setLabelsNeeded( RedCondPair *pair ) | void IpGoto::setLabelsNeeded( RedCondPair *pair ) | |||
{ | { | |||
/* If there is no action with a next statement, then the label will be | /* If there is no action with a next statement, then the label will be | |||
skipping to change at line 617 | skipping to change at line 647 | |||
for ( CondApSet::Iter cond = redFsm->condSet; cond.lte(); cond++ ) | for ( CondApSet::Iter cond = redFsm->condSet; cond.lte(); cond++ ) | |||
setLabelsNeeded( &cond->p ); | setLabelsNeeded( &cond->p ); | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
if ( st->eofAction != 0 ) { | if ( st->eofAction != 0 ) { | |||
for ( GenActionTable::Iter item = st->eofAction-> key; item.lte(); item++ ) | for ( GenActionTable::Iter item = st->eofAction-> key; item.lte(); item++ ) | |||
setLabelsNeeded( item->value->inlineList ); | setLabelsNeeded( item->value->inlineList ); | |||
} | } | |||
} | } | |||
} | } | |||
if ( !noEnd ) { | ||||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) | ||||
{ | ||||
if ( st != redFsm->errState ) | ||||
st->outNeeded = st->labelNeeded; | ||||
} | ||||
} | ||||
} | } | |||
void IpGoto::writeData() | void IpGoto::writeData() | |||
{ | { | |||
STATE_IDS(); | STATE_IDS(); | |||
taNfaTargs(); | taNfaTargs(); | |||
taNfaOffsets(); | taNfaOffsets(); | |||
taNfaPushActions(); | taNfaPushActions(); | |||
taNfaPopTrans(); | taNfaPopTrans(); | |||
} | } | |||
void IpGoto::NFA_FROM_STATE_ACTION_EXEC() | void IpGoto::NFA_FROM_STATE_ACTION_EXEC() | |||
{ | { | |||
if ( redFsm->anyFromStateActions() ) { | // if ( redFsm->anyFromStateActions() ) { | |||
/* Unimplemented feature. Don't have the from state actions array | // /* Unimplemented feature. Don't have the from state actions array | |||
in | in | |||
* this mode. Need to add it, or to alter the NFA pop codegen to | // * this mode. Need to add it, or to alter the NFA pop codegen to | |||
be | be | |||
* consistent with the mode. */ | // * consistent with the mode. */ | |||
assert( false ); | // assert( false ); | |||
} | // } | |||
} | } | |||
void IpGoto::writeExec() | void IpGoto::writeExec() | |||
{ | { | |||
int maxCtrId = redFsm->nextCondId > redFsm->nextTransId ? redFsm->nextCon | ||||
dId : redFsm->nextTransId; | ||||
stLabel = allocateLabels( stLabel, IpLabel::St, redFsm->nextStateId ); | ||||
eofLabel = allocateLabels( eofLabel, IpLabel::TestEof, redFsm->nextStateI | ||||
d ); | ||||
ctrLabel = allocateLabels( ctrLabel, IpLabel::Ctr, maxCtrId ); | ||||
/* Must set labels immediately before writing because we may depend on th e | /* Must set labels immediately before writing because we may depend on th e | |||
* noend write option. */ | * noend write option. */ | |||
setLabelsNeeded(); | setLabelsNeeded(); | |||
testEofUsed = false; | ||||
outLabelUsed = false; | ||||
out << " {\n"; | ||||
if ( redFsm->anyRegNbreak() ) | out << "{\n"; | |||
out << " int _nbreak;\n"; | ||||
if ( redFsm->anyRegCurStateRef() ) | DECLARE( INT(), cpc ); | |||
out << " int _ps = 0;\n"; | DECLARE( INT(), ck ); | |||
DECLARE( INT(), pop_test ); | ||||
DECLARE( INT(), nbreak ); | ||||
DECLARE( INT(), ps ); | ||||
DECLARE( INT(), new_recs ); | ||||
DECLARE( INT(), alt ); | ||||
if ( !noEnd ) { | if ( !noEnd ) { | |||
testEofUsed = true; | ||||
out << | out << | |||
" if ( " << P() << " == " << PE() << " )\n" | " if ( " << P() << " == " << PE() << " )\n" | |||
" goto _test_eof;\n"; | " goto " << _test_eof << ";\n"; | |||
} | } | |||
if ( useAgainLabel() ) { | if ( _again.isReferenced ) { | |||
out << | ||||
" goto " << _resume << ";\n" | ||||
"\n"; | ||||
out << EMIT_LABEL( _again ); | ||||
out << | out << | |||
" goto _resume;\n" | ||||
"\n" | ||||
"_again:\n" | ||||
" switch ( " << vCS() << " ) {\n"; | " switch ( " << vCS() << " ) {\n"; | |||
AGAIN_CASES() << | AGAIN_CASES() << | |||
" }\n" | " }\n" | |||
"\n"; | "\n"; | |||
} | } | |||
if ( useAgainLabel() || redFsm->anyNfaStates() ) | out << EMIT_LABEL( _resume ); | |||
out << "_resume:\n"; | ||||
out << | out << | |||
" switch ( " << vCS() << " )\n" | " switch ( " << vCS() << " ) {\n"; | |||
" {\n"; | ||||
STATE_GOTO_CASES() << | STATE_GOTO_CASES() << | |||
" }\n" | " }\n" | |||
" goto st_out;\n"; | " goto st_out;\n"; | |||
STATE_GOTOS() << | STATE_GOTOS() << | |||
" st_out:\n"; | " st_out:\n"; | |||
EXIT_STATES() << | EXIT_STATES() << | |||
"\n"; | "\n"; | |||
if ( testEofUsed ) | out << EMIT_LABEL( _test_eof ); | |||
out << " _test_eof: {}\n"; | ||||
if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { | if ( redFsm->anyEofActivity() ) { | |||
out << | out << | |||
" if ( " << P() << " == " << vEOF() << " )\n" | " if ( " << P() << " == " << vEOF() << " ) {\n"; | |||
" {\n"; | ||||
out << | out << | |||
" switch ( " << vCS() << " ) {\n"; | " switch ( " << vCS() << " ) {\n"; | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
out << " case " << st->id << ": {\n"; | out << "case " << st->id << ": {\n"; | |||
NFA_PUSH( st ); | NFA_PUSH( st ); | |||
out << "\n\t" << CEND() << "}\n"; | FROM_STATE_ACTION_EMIT( st ); | |||
out << "break;\n}\n"; | ||||
} | } | |||
out << | out << | |||
" }\n"; | " }\n"; | |||
out << | out << | |||
" switch ( " << vCS() << " ) {\n"; | " switch ( " << vCS() << " ) {\n"; | |||
bool okeydokey = false; | bool okeydokey = false; | |||
for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | |||
if ( st->outCondSpace != 0 ) { | if ( st->outCondSpace != 0 ) { | |||
out << " case " << st->id << ": {\n"; | out << "case " << st->id << ": {\n"; | |||
out << "int ck = 0;\n"; | out << ck << " = 0;\n"; | |||
for ( GenCondSet::Iter csi = st->outCondSpace->co ndSet; csi.lte(); csi++ ) { | for ( GenCondSet::Iter csi = st->outCondSpace->co ndSet; csi.lte(); csi++ ) { | |||
out << "if ( "; | out << "if ( "; | |||
CONDITION( out, *csi ); | CONDITION( out, *csi ); | |||
Size condValOffset = (1 << csi.pos()); | Size condValOffset = (1 << csi.pos()); | |||
out << " ) ck += " << condValOffset << "; \n"; | out << " )\n" << ck << " += " << condValO ffset << ";\n"; | |||
} | } | |||
out << " switch ( ck ) {\n"; | out << "switch ( " << ck << " ) {\n"; | |||
for ( CondKeySet::Iter k = st->outCondKeys; k.lte (); k++ ) { | for ( CondKeySet::Iter k = st->outCondKeys; k.lte (); k++ ) { | |||
out << "case " << *k << ": goto _okeydoke y;\n"; | out << "case " << *k << ": goto _okeydoke y;\n"; | |||
okeydokey = true; | okeydokey = true; | |||
} | } | |||
out << "}\n"; | out << "}\n"; | |||
out << vCS() << " = " << ERROR_STATE() << ";\n"; | out << vCS() << " = " << ERROR_STATE() << ";\n"; | |||
out << "goto _out;\n"; | out << "goto " << _pop << ";\n"; | |||
out << "}\n"; | out << "}\n"; | |||
} | } | |||
} | } | |||
out << | out << | |||
" }\n"; | " }\n"; | |||
if ( okeydokey ) { | if ( okeydokey ) { | |||
out << | out << | |||
"_okeydokey: {}\n"; | "_okeydokey: {}\n"; | |||
} | } | |||
out << | out << | |||
" switch ( " << vCS() << " ) {\n"; | " switch ( " << vCS() << " ) {\n"; | |||
FINISH_CASES() << | FINISH_CASES() << | |||
" }\n" | " }\n"; | |||
out << | ||||
" }\n" | " }\n" | |||
"\n"; | "\n"; | |||
} | } | |||
if ( outLabelUsed ) | out << | |||
out << " _out: {}\n"; | "if ( " << vCS() << " >= " << FIRST_FINAL_STATE() << " )\n" | |||
" goto " << _out << "; "; | ||||
out << EMIT_LABEL( _pop ); | ||||
if ( redFsm->anyNfaStates() ) { | ||||
out << | ||||
"if ( nfa_len == 0 )\n" | ||||
" goto " << _out << ";\n" | ||||
"\n"; | ||||
out << | ||||
"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"; | ||||
} | ||||
NFA_POP(); | out << EMIT_LABEL( _out ); | |||
out << | out << | |||
" }\n"; | "}\n"; | |||
} | } | |||
End of changes. 76 change blocks. | ||||
150 lines changed or deleted | 228 lines changed or added |