{
out << INDENT_U() << "begin"
<< INDENT_S() << CS() << " = " << gotoDest
- << INDENT_S() << "_again.call " << CTRL_FLOW()
+ << INDENT_S() << "_break_again = true; break " // break _again
<< INDENT_D() << "end ";
}
<< INDENT_S() << CS() << " = (";
INLINE_LIST( out, ilItem->children, 0, inFinish );
out << ")"
- << INDENT_S() << "_again.call " << CTRL_FLOW()
+ << INDENT_S() << "_break_again = true; break " // break _again
<< INDENT_D() << "end ";
}
<< INDENT_S() << STACK() << "[" << TOP() << "] = " << CS()
<< INDENT_S() << TOP() << "+= 1"
<< INDENT_S() << CS() << " = " << callDest
- << INDENT_S() << "_again.call " << CTRL_FLOW()
+ << INDENT_S() << "_break_again = true; break " // break _again
<< INDENT_D() << "end ";
}
<< INDENT_S() << CS() << " = (";
INLINE_LIST( out, ilItem->children, targState, inFinish );
out << ")"
- << INDENT_S() << "_again.call " << CTRL_FLOW()
+ << INDENT_S() << "_break_again = true; break " // break _again
<< INDENT_D() << "end ";
}
out << INDENT_U() << "begin"
<< INDENT_S() << TOP() << " -= 1"
<< INDENT_S() << CS() << " = " << STACK() << "[" << TOP() << "]"
- << INDENT_S() << "_again.call " << CTRL_FLOW()
+ << INDENT_S() << "_break_again = true; break " // break _again
<< INDENT_D() << "end ";
}
void RubyCodeGen::BREAK( ostream &out, int targState )
{
- out << "_out.call " << CTRL_FLOW();
+ out << "_break_resume = true; break\n";
}
void RubyCodeGen::COND_TRANSLATE()
out << INDENT_S() << "_keys = " << KO() << "[" << CS() << "]"
<< INDENT_S() << "_trans = " << IO() << "[" << CS() << "]"
<< INDENT_S() << "_klen = " << SL() << "[" << CS() << "]"
+ << INDENT_S() << "_break_match = false"
<< INDENT_S()
- << INDENT_U() << "callcc do |_match|"
+ << INDENT_U() << "begin"
<< INDENT_U() << "if _klen > 0"
<< INDENT_S() << "_lower = _keys"
<< INDENT_S() << "_upper = _keys + _klen - 1"
<< INDENT_O() << "_lower = _mid + 1"
<< INDENT_U() << "else"
<< INDENT_S() << "_trans += (_mid - _keys)"
- << INDENT_S() << "_match.call"
+ << INDENT_S() << "_break_match = true"
+ << INDENT_S() << "break"
<< INDENT_D() << "end"
<< INDENT_D() << "end # loop"
+ << INDENT_S() << "break if _break_match"
<< INDENT_S() << "_keys += _klen"
<< INDENT_S() << "_trans += _klen"
<< INDENT_D() << "end"
<< INDENT_O() << "_lower = _mid + 2"
<< INDENT_U() << "else"
<< INDENT_S() << "_trans += ((_mid - _keys) >> 1)"
- << INDENT_S() << "_match.call"
+ << INDENT_S() << "_break_match = true"
+ << INDENT_S() << "break"
<< INDENT_D() << "end"
<< INDENT_D() << "end # loop"
+ << INDENT_S() << "break if _break_match"
<< INDENT_S() << "_trans += _klen"
<< INDENT_D() << "end"
- << INDENT_D() << "end # cc _match" ;
+ << INDENT_D() << "end while false";
}
void RubyCodeGen::writeExec()
{
- out << INDENT_U() << "callcc do |_out|"
+ out << INDENT_U() << "begin"
<< INDENT_S() << "_klen, _trans, _keys";
if ( redFsm->anyRegCurStateRef() )
out << " = nil" ;
if ( hasEnd )
- out << INDENT_S() << "_out.call if " << P() << " == " << PE() ;
+ out << INDENT_S() << "if " << P() << " != " << PE() ;
if ( redFsm->errState != 0 )
- out << INDENT_S() << "_out.call if " << CS() << " == " << redFsm->errState->id ;
+ out << INDENT_S() << "if " << CS() << " != " << redFsm->errState->id;
- out << INDENT_S() << "_resume = nil"
- << INDENT_S() << "callcc { |_cc| _resume = _cc }" ;
+ /* Open the _resume loop. */
+ out << INDENT_S() << "while true"
+ << INDENT_S() << "_break_resume = false";
- if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
- redFsm->anyActionCalls() || redFsm->anyActionRets() )
- out << INDENT_U() << "callcc do |_again|" ;
+ /* Open the _again loop. */
+ out << INDENT_S() << "begin"
+ << INDENT_S() << "_break_again = false";
if ( redFsm->anyFromStateActions() ) {
out << INDENT_S() << "_acts = " << FSA() << "[" << CS() << "]"
FROM_STATE_ACTION_SWITCH()
<< INDENT_D() << "end # from state action switch"
<< INDENT_D() << "end"
+ << INDENT_D() << "break if _break_again"
<< INDENT_S();
}
out << INDENT_S() << CS() << " = " << TT() << "[_trans]" ;
if ( redFsm->anyRegActions() ) {
- out << INDENT_S() << "_again.call if " << TA() << "[_trans] == 0"
+ /* break _again */
+ out << INDENT_S() << "break if " << TA() << "[_trans] == 0"
<< INDENT_S()
<< INDENT_S() << "_acts = " << TA() << "[_trans]"
<< INDENT_S() << "_nacts = " << A() << "[_acts]"
<< INDENT_S() << "_acts += 1"
<< INDENT_U() << "case " << A() << "[_acts - 1]" ;
ACTION_SWITCH()
- << INDENT_D() << "end # action switch"
+ << INDENT_D() << "end # action switch"
<< INDENT_D() << "end"
+ /* Not necessary as long as there is no code between here and the
+ * end while false. */
+ << INDENT_D() << "break if _break_again"
<< INDENT_S();
}
- if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
- redFsm->anyActionCalls() || redFsm->anyActionRets() )
- out << INDENT_D() << "end # cc _again";
+ /* Close the again loop. */
+ out << INDENT_S() << "end while false";
+ out << INDENT_S() << "break if _break_resume";
if ( redFsm->anyToStateActions() ) {
out << INDENT_S() << "_acts = " << TSA() << "[" << CS() << "]"
}
if ( redFsm->errState != 0 )
- out << INDENT_S() << "_out.call if " << CS() << " == " << redFsm->errState->id ;
+ out << INDENT_S() << "break if " << CS() << " == " << redFsm->errState->id ;
out << INDENT_S() << P() << " += 1" ;
if ( hasEnd )
- out << INDENT_S() << "_resume.call if " << P() << " != " << PE();
+ out << INDENT_S() << "break if " << P() << " == " << PE();
+
+ /* Close the resume loop. */
+ out << INDENT_S() << "end";
- out << INDENT_D() << "end # cc _out" ;
+ /* The if guarding on the error state. */
+ if ( redFsm->errState != 0 )
+ out << INDENT_S() << "end";
+
+ /* The if guarding on empty string. */
+ if ( hasEnd )
+ out << INDENT_S() << "end";
+
+ /* Wrapping the execute block. */
+ out << INDENT_D() << "end" ;
}
void RubyCodeGen::writeEOF()
return ret.str();
}
-string RubyCodeGen::CTRL_FLOW()
-{
- return "if (true)";
-}
-
void RubyCodeGen::ACTION( ostream &ret, Action *action, int targState, bool inFinish )
{
/* Write the preprocessor line info for going into the source file. */
public:
- virtual ostream &START_ARRAY_LINE();
- virtual ostream &ARRAY_ITEM( string item, int count, bool last );
- virtual ostream &END_ARRAY_LINE();
+ ostream &START_ARRAY_LINE();
+ ostream &ARRAY_ITEM( string item, int count, bool last );
+ ostream &END_ARRAY_LINE();
string FSM_NAME();
string START_STATE_ID();
bool useIndicies;
public:
- virtual string NULL_ITEM();
- virtual ostream &OPEN_ARRAY( string type, string name );
- virtual ostream &CLOSE_ARRAY();
- virtual ostream &STATIC_VAR( string type, string name );
- virtual string ARR_OFF( string ptr, string offset );
- virtual string GET_KEY();
- virtual string CTRL_FLOW();
- virtual void ACTION( ostream &ret, Action *action, int targState, bool inFinish );
+ string NULL_ITEM();
+ ostream &OPEN_ARRAY( string type, string name );
+ ostream &CLOSE_ARRAY();
+ ostream &STATIC_VAR( string type, string name );
+ string ARR_OFF( string ptr, string offset );
+ string GET_KEY();
+ void ACTION( ostream &ret, Action *action, int targState, bool inFinish );
protected:
string INDENT_S() { return INDENT(indent_level); }
string INDENT_O() { return INDENT(indent_level--); }
private:
- virtual string INDENT(int level);
+ string INDENT(int level);
int indent_level;
};