*/
#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; */
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)
{}
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;
}
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 \"" <<