Line directives need to use the fileName stored in the InputLoc stuctures from
[external/ragel.git] / ragel / gendata.cpp
index 14124eb..8c57e2c 100644 (file)
  */
 
 #include "gendata.h"
+#include "ragel.h"
 #include <iostream>
 
+/*
+ * Code generators.
+ */
+
+#include "cstable.h"
+#include "csftable.h"
+#include "csflat.h"
+#include "csfflat.h"
+#include "csgoto.h"
+#include "csfgoto.h"
+#include "csipgoto.h"
+#include "cssplit.h"
+
+#include "cdtable.h"
+#include "cdftable.h"
+#include "cdflat.h"
+#include "cdfflat.h"
+#include "cdgoto.h"
+#include "cdfgoto.h"
+#include "cdipgoto.h"
+#include "cdsplit.h"
+
+#include "dotcodegen.h"
+
+#include "javacodegen.h"
+
+#include "rubytable.h"
+#include "rubyftable.h"
+#include "rubyflat.h"
+#include "rubyfflat.h"
+#include "rbxgoto.h"
+
+string itoa( int i )
+{
+       char buf[16];
+       sprintf( buf, "%i", i );
+       return buf;
+}
+
+using std::cout;
 using std::cerr;
 using std::endl;
 
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *dotMakeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *codeGen = new GraphvizDotGen(out);
+
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+
+       /* For normal code generation we want a transition on every character so we never
+        * end up in an undefined state. For graphviz this just clutters the
+        * drawing so we turn it off. */
+       codeGen->wantComplete = false;
+
+       return codeGen;
+}
+
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *cdMakeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *codeGen = 0;
+       switch ( hostLang->lang ) {
+       case HostLang::C:
+               switch ( codeStyle ) {
+               case GenTables:
+                       codeGen = new CTabCodeGen(out);
+                       break;
+               case GenFTables:
+                       codeGen = new CFTabCodeGen(out);
+                       break;
+               case GenFlat:
+                       codeGen = new CFlatCodeGen(out);
+                       break;
+               case GenFFlat:
+                       codeGen = new CFFlatCodeGen(out);
+                       break;
+               case GenGoto:
+                       codeGen = new CGotoCodeGen(out);
+                       break;
+               case GenFGoto:
+                       codeGen = new CFGotoCodeGen(out);
+                       break;
+               case GenIpGoto:
+                       codeGen = new CIpGotoCodeGen(out);
+                       break;
+               case GenSplit:
+                       codeGen = new CSplitCodeGen(out);
+                       break;
+               }
+               break;
+
+       case HostLang::D:
+               switch ( codeStyle ) {
+               case GenTables:
+                       codeGen = new DTabCodeGen(out);
+                       break;
+               case GenFTables:
+                       codeGen = new DFTabCodeGen(out);
+                       break;
+               case GenFlat:
+                       codeGen = new DFlatCodeGen(out);
+                       break;
+               case GenFFlat:
+                       codeGen = new DFFlatCodeGen(out);
+                       break;
+               case GenGoto:
+                       codeGen = new DGotoCodeGen(out);
+                       break;
+               case GenFGoto:
+                       codeGen = new DFGotoCodeGen(out);
+                       break;
+               case GenIpGoto:
+                       codeGen = new DIpGotoCodeGen(out);
+                       break;
+               case GenSplit:
+                       codeGen = new DSplitCodeGen(out);
+                       break;
+               }
+               break;
+
+       default: break;
+       }
+
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+
+       return codeGen;
+}
+
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *javaMakeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *codeGen = new JavaTabCodeGen(out);
+
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+
+       return codeGen;
+}
+
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *rubyMakeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *codeGen = 0;
+       switch ( codeStyle ) {
+               case GenTables: 
+                       codeGen = new RubyTabCodeGen(out);
+                       break;
+               case GenFTables:
+                       codeGen = new RubyFTabCodeGen(out);
+                       break;
+               case GenFlat:
+                       codeGen = new RubyFlatCodeGen(out);
+                       break;
+               case GenFFlat:
+                       codeGen = new RubyFFlatCodeGen(out);
+                       break;
+               case GenGoto:
+                       if ( rubyImpl == Rubinius ) {
+                               codeGen = new RbxGotoCodeGen(out);
+                       } else {
+                               cerr << "Goto style is still _very_ experimental " 
+                                       "and only supported using Rubinius.\n"
+                                       "You may want to enable the --rbx flag "
+                                       " to give it a try.\n";
+                               exit(1);
+                       }
+                       break;
+               default:
+                       cout << "Invalid code style\n";
+                       exit(1);
+                       break;
+       }
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+
+       return codeGen;
+}
+
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *csharpMakeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *codeGen = 0;
+
+       switch ( codeStyle ) {
+       case GenTables:
+               codeGen = new CSharpTabCodeGen(out);
+               break;
+       case GenFTables:
+               codeGen = new CSharpFTabCodeGen(out);
+               break;
+       case GenFlat:
+               codeGen = new CSharpFlatCodeGen(out);
+               break;
+       case GenFFlat:
+               codeGen = new CSharpFFlatCodeGen(out);
+               break;
+       case GenGoto:
+               codeGen = new CSharpGotoCodeGen(out);
+               break;
+       case GenFGoto:
+               codeGen = new CSharpFGotoCodeGen(out);
+               break;
+       case GenIpGoto:
+               codeGen = new CSharpIpGotoCodeGen(out);
+               break;
+       case GenSplit:
+               codeGen = new CSharpSplitCodeGen(out);
+               break;
+       }
+
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+
+       return codeGen;
+}
+
+
+CodeGenData *makeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out )
+{
+       CodeGenData *cgd = 0;
+       if ( generateDot )
+               cgd = dotMakeCodeGen( sourceFileName, fsmName, out );
+       else if ( hostLang == &hostLangC )
+               cgd = cdMakeCodeGen( sourceFileName, fsmName, out );
+       else if ( hostLang == &hostLangD )
+               cgd = cdMakeCodeGen( sourceFileName, fsmName, out );
+       else if ( hostLang == &hostLangJava )
+               cgd = javaMakeCodeGen( sourceFileName, fsmName, out );
+       else if ( hostLang == &hostLangRuby )
+               cgd = rubyMakeCodeGen( sourceFileName, fsmName, out );
+       else if ( hostLang == &hostLangCSharp )
+               cgd = csharpMakeCodeGen( sourceFileName, fsmName, out );
+       return cgd;
+}
+
+void lineDirective( ostream &out, const char *fileName, int line )
+{
+       if ( !generateDot ) {
+               if ( hostLang == &hostLangC )
+                       cdLineDirective( out, fileName, line );
+               else if ( hostLang == &hostLangD )
+                       cdLineDirective( out, fileName, line );
+               else if ( hostLang == &hostLangJava )
+                       javaLineDirective( out, fileName, line );
+               else if ( hostLang == &hostLangRuby )
+                       rubyLineDirective( out, fileName, line );
+               else if ( hostLang == &hostLangCSharp )
+                       csharpLineDirective( out, fileName, line );
+       }
+}
+
+void genLineDirective( ostream &out )
+{
+       std::streambuf *sbuf = out.rdbuf();
+       output_filter *filter = static_cast<output_filter*>(sbuf);
+       lineDirective( out, filter->fileName, filter->line + 1 );
+}
+
+
 /* Total error count. */
 /* int gblErrorCount = 0; */
 
@@ -56,13 +316,13 @@ CodeGenData::CodeGenData( ostream &out )
        tokstartExpr(0),
        tokendExpr(0),
        dataExpr(0),
-       wantComplete(0),
+       wantComplete(true),
        hasLongestMatch(false),
-       hasEnd(true),
-       dataPrefix(true),
-       writeFirstFinal(true),
-       writeErr(true),
-       writeCS(true)
+       noEnd(false),
+       noPrefix(false),
+       noFinal(false),
+       noError(false),
+       noCS(false)
 {}
 
 
@@ -78,13 +338,12 @@ void CodeGenData::initActionList( unsigned long length )
                actionList.append( allActions+a );
 }
 
-void CodeGenData::newAction( int anum, const char *name, int line, 
-               int col, GenInlineList *inlineList )
+void CodeGenData::newAction( int anum, const char *name,
+               const InputLoc &loc, GenInlineList *inlineList )
 {
        allActions[anum].actionId = anum;
        allActions[anum].name = name;
-       allActions[anum].loc.line = line;
-       allActions[anum].loc.col = col;
+       allActions[anum].loc = loc;
        allActions[anum].inlineList = inlineList;
 }
 
@@ -668,59 +927,71 @@ void CodeGenData::analyzeMachine()
        setValueLimits();
 }
 
+void CodeGenData::write_option_error( InputLoc &loc, char *arg )
+{
+       source_warning(loc) << "unrecognized write option \"" << arg << "\"" << endl;
+}
+
 void CodeGenData::writeStatement( InputLoc &loc, int nargs, char **args )
 {
        /* FIXME: This should be moved to the virtual functions in the code
         * generators.
         *
         * Force a newline. */
-       out << "\n";
+       out << '\n';
        genLineDirective( out );
 
        if ( strcmp( args[0], "data" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
                        if ( strcmp( args[i], "noerror" ) == 0 )
-                               writeErr = false;
+                               noError = true;
                        else if ( strcmp( args[i], "noprefix" ) == 0 )
-                               dataPrefix = false;
+                               noPrefix = true;
                        else if ( strcmp( args[i], "nofinal" ) == 0 )
-                               writeFirstFinal = false;
-                       else {
-                               source_warning(loc) << "unrecognized write option \"" << 
-                                               args[i] << "\"" << endl;
-                       }
+                               noFinal = true;
+                       else
+                               write_option_error( loc, args[i] );
                }
                writeData();
        }
        else if ( strcmp( args[0], "init" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
                        if ( strcmp( args[i], "nocs" ) == 0 )
-                               writeCS = false;
-                       else {
-                               source_warning(loc) << "unrecognized write option \"" << 
-                                               args[i] << "\"" << endl;
-                       }
+                               noCS = true;
+                       else
+                               write_option_error( loc, args[i] );
                }
                writeInit();
        }
        else if ( strcmp( args[0], "exec" ) == 0 ) {
                for ( int i = 1; i < nargs; i++ ) {
                        if ( strcmp( args[i], "noend" ) == 0 )
-                               hasEnd = false;
-                       else {
-                               source_warning(loc) << "unrecognized write option \"" << 
-                                               args[i] << "\"" << endl;
-                       }
+                               noEnd = true;
+                       else
+                               write_option_error( loc, args[i] );
                }
                writeExec();
        }
        else if ( strcmp( args[0], "exports" ) == 0 ) {
-               for ( int i = 1; i < nargs; i++ ) {
-                       source_warning(loc) << "unrecognized write option \"" << 
-                                       args[i] << "\"" << endl;
-               }
+               for ( int i = 1; i < nargs; i++ )
+                       write_option_error( loc, args[i] );
                writeExports();
        }
+       else if ( strcmp( args[0], "start" ) == 0 ) {
+               for ( int i = 1; i < nargs; i++ )
+                       write_option_error( loc, args[i] );
+               writeStart();
+       }
+       else if ( strcmp( args[0], "first_final" ) == 0 ) {
+               for ( int i = 1; i < nargs; i++ )
+                       write_option_error( loc, args[i] );
+               writeFirstFinal();
+       }
+       else if ( strcmp( args[0], "error" ) == 0 ) {
+               for ( int i = 1; i < nargs; i++ )
+                       write_option_error( loc, args[i] );
+               writeError();
+       }
        else {
                /* EMIT An error here. */
                source_error(loc) << "unrecognized write command \"" <<