Started on the move back to a single executable. The backend programs are now a
[external/ragel.git] / rlgen-cd / fsmcodegen.cpp
index 317c08d..ab8f4ad 100644 (file)
@@ -36,14 +36,14 @@ using std::string;
 using std::cerr;
 using std::endl;
 
-void lineDirective( ostream &out, char *fileName, int line )
+void cdLineDirective( ostream &out, const char *fileName, int line )
 {
        if ( noLineDirectives )
                out << "/* ";
 
        /* Write the preprocessor line info for to the input file. */
        out << "#line " << line  << " \"";
-       for ( char *pc = fileName; *pc != 0; pc++ ) {
+       for ( const char *pc = fileName; *pc != 0; pc++ ) {
                if ( *pc == '\\' )
                        out << "\\\\";
                else
@@ -57,11 +57,11 @@ void lineDirective( ostream &out, char *fileName, int line )
        out << '\n';
 }
 
-void genLineDirective( ostream &out )
+void FsmCodeGen::genLineDirective( ostream &out )
 {
        std::streambuf *sbuf = out.rdbuf();
        output_filter *filter = static_cast<output_filter*>(sbuf);
-       lineDirective( out, filter->fileName, filter->line + 1 );
+       cdLineDirective( out, filter->fileName, filter->line + 1 );
 }
 
 
@@ -140,7 +140,7 @@ string FsmCodeGen::ACCESS()
 {
        ostringstream ret;
        if ( accessExpr != 0 )
-               INLINE_LIST( ret, accessExpr, 0, false );
+               INLINE_LIST( ret, accessExpr, 0, false, false );
        return ret.str();
 }
 
@@ -152,7 +152,7 @@ string FsmCodeGen::P()
                ret << "p";
        else {
                ret << "(";
-               INLINE_LIST( ret, pExpr, 0, false );
+               INLINE_LIST( ret, pExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -165,7 +165,7 @@ string FsmCodeGen::PE()
                ret << "pe";
        else {
                ret << "(";
-               INLINE_LIST( ret, peExpr, 0, false );
+               INLINE_LIST( ret, peExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -178,7 +178,7 @@ string FsmCodeGen::EOFV()
                ret << "eof";
        else {
                ret << "(";
-               INLINE_LIST( ret, eofExpr, 0, false );
+               INLINE_LIST( ret, eofExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -192,7 +192,7 @@ string FsmCodeGen::CS()
        else {
                /* Emit the user supplied method of retrieving the key. */
                ret << "(";
-               INLINE_LIST( ret, csExpr, 0, false );
+               INLINE_LIST( ret, csExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -205,7 +205,7 @@ string FsmCodeGen::TOP()
                ret << ACCESS() + "top";
        else {
                ret << "(";
-               INLINE_LIST( ret, topExpr, 0, false );
+               INLINE_LIST( ret, topExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -218,7 +218,7 @@ string FsmCodeGen::STACK()
                ret << ACCESS() + "stack";
        else {
                ret << "(";
-               INLINE_LIST( ret, stackExpr, 0, false );
+               INLINE_LIST( ret, stackExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -231,7 +231,7 @@ string FsmCodeGen::ACT()
                ret << ACCESS() + "act";
        else {
                ret << "(";
-               INLINE_LIST( ret, actExpr, 0, false );
+               INLINE_LIST( ret, actExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -241,10 +241,10 @@ string FsmCodeGen::TOKSTART()
 {
        ostringstream ret;
        if ( tokstartExpr == 0 )
-               ret << ACCESS() + "tokstart";
+               ret << ACCESS() + "ts";
        else {
                ret << "(";
-               INLINE_LIST( ret, tokstartExpr, 0, false );
+               INLINE_LIST( ret, tokstartExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -254,10 +254,10 @@ string FsmCodeGen::TOKEND()
 {
        ostringstream ret;
        if ( tokendExpr == 0 )
-               ret << ACCESS() + "tokend";
+               ret << ACCESS() + "te";
        else {
                ret << "(";
-               INLINE_LIST( ret, tokendExpr, 0, false );
+               INLINE_LIST( ret, tokendExpr, 0, false, false );
                ret << ")";
        }
        return ret.str();
@@ -285,7 +285,7 @@ string FsmCodeGen::GET_KEY()
        if ( getKeyExpr != 0 ) { 
                /* Emit the user supplied method of retrieving the key. */
                ret << "(";
-               INLINE_LIST( ret, getKeyExpr, 0, false );
+               INLINE_LIST( ret, getKeyExpr, 0, false, false );
                ret << ")";
        }
        else {
@@ -317,46 +317,54 @@ string FsmCodeGen::KEY( Key key )
        return ret.str();
 }
 
-void FsmCodeGen::EXEC( ostream &ret, InlineItem *item, int targState, int inFinish )
+void FsmCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
 {
        /* The parser gives fexec two children. The double brackets are for D
         * code. If the inline list is a single word it will get interpreted as a
         * C-style cast by the D compiler. */
        ret << "{" << P() << " = ((";
-       INLINE_LIST( ret, item->children, targState, inFinish );
+       INLINE_LIST( ret, item->children, targState, inFinish, false );
        ret << "))-1;}";
 }
 
-void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item, 
-               int targState, int inFinish )
+void FsmCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, 
+               int targState, int inFinish, bool csForced )
 {
        ret << 
                "       switch( " << ACT() << " ) {\n";
 
-       for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
+       bool haveDefault = false;
+       for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
                /* Write the case label, the action and the case break. */
-               ret << "        case " << lma->lmId << ":\n";
+               if ( lma->lmId < 0 ) {
+                       ret << "        default:\n";
+                       haveDefault = true;
+               }
+               else
+                       ret << "        case " << lma->lmId << ":\n";
 
                /* Write the block and close it off. */
                ret << "        {";
-               INLINE_LIST( ret, lma->children, targState, inFinish );
+               INLINE_LIST( ret, lma->children, targState, inFinish, csForced );
                ret << "}\n";
 
                ret << "        break;\n";
        }
-       /* Default required for D code. */
+
+       if ( hostLang->lang == HostLang::D && !haveDefault )
+               ret << "        default: break;";
+
        ret << 
-               "       default: break;\n"
                "       }\n"
                "\t";
 }
 
-void FsmCodeGen::SET_ACT( ostream &ret, InlineItem *item )
+void FsmCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
 {
        ret << ACT() << " = " << item->lmId << ";";
 }
 
-void FsmCodeGen::SET_TOKEND( ostream &ret, InlineItem *item )
+void FsmCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
 {
        /* The tokend action sets tokend. */
        ret << TOKEND() << " = " << P();
@@ -365,33 +373,33 @@ void FsmCodeGen::SET_TOKEND( ostream &ret, InlineItem *item )
        out << ";";
 }
 
-void FsmCodeGen::GET_TOKEND( ostream &ret, InlineItem *item )
+void FsmCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
 {
        ret << TOKEND();
 }
 
-void FsmCodeGen::INIT_TOKSTART( ostream &ret, InlineItem *item )
+void FsmCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
 {
        ret << TOKSTART() << " = " << NULL_ITEM() << ";";
 }
 
-void FsmCodeGen::INIT_ACT( ostream &ret, InlineItem *item )
+void FsmCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
 {
        ret << ACT() << " = 0;";
 }
 
-void FsmCodeGen::SET_TOKSTART( ostream &ret, InlineItem *item )
+void FsmCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
 {
        ret << TOKSTART() << " = " << P() << ";";
 }
 
-void FsmCodeGen::SUB_ACTION( ostream &ret, InlineItem *item, 
-               int targState, bool inFinish )
+void FsmCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, 
+               int targState, bool inFinish, bool csForced )
 {
        if ( item->children->length() > 0 ) {
                /* Write the block and close it off. */
                ret << "{";
-               INLINE_LIST( ret, item->children, targState, inFinish );
+               INLINE_LIST( ret, item->children, targState, inFinish, csForced );
                ret << "}";
        }
 }
@@ -399,82 +407,82 @@ void FsmCodeGen::SUB_ACTION( ostream &ret, InlineItem *item,
 
 /* Write out an inline tree structure. Walks the list and possibly calls out
  * to virtual functions than handle language specific items in the tree. */
-void FsmCodeGen::INLINE_LIST( ostream &ret, InlineList *inlineList, 
-               int targState, bool inFinish )
+void FsmCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, 
+               int targState, bool inFinish, bool csForced )
 {
-       for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
+       for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
                switch ( item->type ) {
-               case InlineItem::Text:
+               case GenInlineItem::Text:
                        ret << item->data;
                        break;
-               case InlineItem::Goto:
+               case GenInlineItem::Goto:
                        GOTO( ret, item->targState->id, inFinish );
                        break;
-               case InlineItem::Call:
+               case GenInlineItem::Call:
                        CALL( ret, item->targState->id, targState, inFinish );
                        break;
-               case InlineItem::Next:
+               case GenInlineItem::Next:
                        NEXT( ret, item->targState->id, inFinish );
                        break;
-               case InlineItem::Ret:
+               case GenInlineItem::Ret:
                        RET( ret, inFinish );
                        break;
-               case InlineItem::PChar:
+               case GenInlineItem::PChar:
                        ret << P();
                        break;
-               case InlineItem::Char:
+               case GenInlineItem::Char:
                        ret << GET_KEY();
                        break;
-               case InlineItem::Hold:
+               case GenInlineItem::Hold:
                        ret << P() << "--;";
                        break;
-               case InlineItem::Exec:
+               case GenInlineItem::Exec:
                        EXEC( ret, item, targState, inFinish );
                        break;
-               case InlineItem::Curs:
+               case GenInlineItem::Curs:
                        CURS( ret, inFinish );
                        break;
-               case InlineItem::Targs:
+               case GenInlineItem::Targs:
                        TARGS( ret, inFinish, targState );
                        break;
-               case InlineItem::Entry:
+               case GenInlineItem::Entry:
                        ret << item->targState->id;
                        break;
-               case InlineItem::GotoExpr:
+               case GenInlineItem::GotoExpr:
                        GOTO_EXPR( ret, item, inFinish );
                        break;
-               case InlineItem::CallExpr:
+               case GenInlineItem::CallExpr:
                        CALL_EXPR( ret, item, targState, inFinish );
                        break;
-               case InlineItem::NextExpr:
+               case GenInlineItem::NextExpr:
                        NEXT_EXPR( ret, item, inFinish );
                        break;
-               case InlineItem::LmSwitch:
-                       LM_SWITCH( ret, item, targState, inFinish );
+               case GenInlineItem::LmSwitch:
+                       LM_SWITCH( ret, item, targState, inFinish, csForced );
                        break;
-               case InlineItem::LmSetActId:
+               case GenInlineItem::LmSetActId:
                        SET_ACT( ret, item );
                        break;
-               case InlineItem::LmSetTokEnd:
+               case GenInlineItem::LmSetTokEnd:
                        SET_TOKEND( ret, item );
                        break;
-               case InlineItem::LmGetTokEnd:
+               case GenInlineItem::LmGetTokEnd:
                        GET_TOKEND( ret, item );
                        break;
-               case InlineItem::LmInitTokStart:
+               case GenInlineItem::LmInitTokStart:
                        INIT_TOKSTART( ret, item );
                        break;
-               case InlineItem::LmInitAct:
+               case GenInlineItem::LmInitAct:
                        INIT_ACT( ret, item );
                        break;
-               case InlineItem::LmSetTokStart:
+               case GenInlineItem::LmSetTokStart:
                        SET_TOKSTART( ret, item );
                        break;
-               case InlineItem::SubAction:
-                       SUB_ACTION( ret, item, targState, inFinish );
+               case GenInlineItem::SubAction:
+                       SUB_ACTION( ret, item, targState, inFinish, csForced );
                        break;
-               case InlineItem::Break:
-                       BREAK( ret, targState );
+               case GenInlineItem::Break:
+                       BREAK( ret, targState, csForced );
                        break;
                }
        }
@@ -492,22 +500,23 @@ string FsmCodeGen::LDIR_PATH( char *path )
        return ret.str();
 }
 
-void FsmCodeGen::ACTION( ostream &ret, Action *action, int targState, bool inFinish )
+void FsmCodeGen::ACTION( ostream &ret, Action *action, int targState, 
+               bool inFinish, bool csForced )
 {
        /* Write the preprocessor line info for going into the source file. */
-       lineDirective( ret, sourceFileName, action->loc.line );
+       cdLineDirective( ret, sourceFileName, action->loc.line );
 
        /* Write the block and close it off. */
        ret << "\t{";
-       INLINE_LIST( ret, action->inlineList, targState, inFinish );
+       INLINE_LIST( ret, action->inlineList, targState, inFinish, csForced );
        ret << "}\n";
 }
 
 void FsmCodeGen::CONDITION( ostream &ret, Action *condition )
 {
        ret << "\n";
-       lineDirective( ret, sourceFileName, condition->loc.line );
-       INLINE_LIST( ret, condition->inlineList, 0, false );
+       cdLineDirective( ret, sourceFileName, condition->loc.line );
+       INLINE_LIST( ret, condition->inlineList, 0, false, false );
 }
 
 string FsmCodeGen::ERROR_STATE()
@@ -805,13 +814,13 @@ void FsmCodeGen::finishRagelDef()
        calcIndexSize();
 }
 
-ostream &FsmCodeGen::source_warning( const InputLoc &loc )
+ostream &FsmCodeGen::source_warning( const GenInputLoc &loc )
 {
        cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
        return cerr;
 }
 
-ostream &FsmCodeGen::source_error( const InputLoc &loc )
+ostream &FsmCodeGen::source_error( const GenInputLoc &loc )
 {
        gblErrorCount += 1;
        assert( sourceFileName != 0 );